Skip to content

fix(ios): iOS 27 DDI mount loops on Hangup failure (mount succeeds, cleanup rejected) #315

Description

@maatheusgois-dd

Summary

GADS v5.7.0 fails to set up iOS 27 (beta) devices. The DDI mount succeeds, but go-ios's trailing Hangup cleanup command fails because iOS 27 closes the mobile_image_mounter lockdown connection immediately after the mount. GADS treats this cleanup error as a fatal mount failure and resets the device in a ~12s retry loop, never reaching WDA.

Device

Field Value
Device iPhone 14 (iPhone14,7)
UDID 00008110-00040994117A602E
iOS 27.0 (27A5209h)
Xcode 26.3 (17C529)
GADS v5.7.0
go-ios v1.0.202

Error

Failed to mount Developer Disk Image (DDI) for device `00008110-00040994117A602E` - failed to mount DDI: MountImage: HangUp command failed: Write: only 0 bytes were written instead of 229

Repeats every ~12s in an infinite retry loop.

Root cause

The go-ios personalized DDI mount flow (personalized_image_mounter.go:67-130) is:

  1. Query identifiers → get nonce → get Apple TSS signature
  2. sendUploadRequest → stream DMG bytes → waitForUploadComplete
  3. mountPersonalizedImagethe actual mount; returns nil (succeeds)
  4. hangUp ← sends {"Command":"Hangup"} over the same lockdown connection

On iOS 27, the device closes the mobile_image_mounter lockdown connection immediately after step 3 succeeds. Step 4's write gets 0 bytes → Write: only 0 bytes were written instead of 229 → wrapped as MountImage: HangUp command failed.

GADS's mountDeveloperImage() (provider/devices/ios.go:104) treats any non-"already mounted" error as fatal and calls resetWithError, which resets the device and triggers the retry loop — even though the DDI is already mounted.

This is not a lockdown-vs-CoreDevice protocol issue. The MountImage/Personalized plist command works; only the trailing Hangup is rejected. Xcode's devicectl uses CoreDevice and never sends Hangup, so it doesn't hit this.

Note: the latest go-ios (v1.0.218) adds a QueryPersonalizationManifest optimization but still sends the same Hangup — so bumping go-ios alone won't fix this.

Fix

When imagemounter.MountImage fails with "HangUp command failed", log a warning and re-connect to verify the DDI is mounted via ListImages. If an image is mounted, proceed to WDA. If verification fails, reset as before.

if strings.Contains(err.Error(), "HangUp command failed") {
    logger.ProviderLogger.LogWarn("ios_device_setup", ...)
    return d.verifyDDIMounted()
}

verifyDDIMounted opens a fresh NewImageMounter + ListImages on a new lockdown connection, independent of the closed mounter connection.

Verification

  • go build ./provider/devices/
  • go vet ./provider/devices/
  • Live device verification not yet done — needs the iPhone 14 on iOS 27. The fix is testable by confirming setup proceeds past DDI mount to setupTunnelIfNeeded() → WDA install.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions