Blolabel
← Notes
event 8 min read

An iOS point release stopped the automation runner, and every check still reported success

devicectl said success. The process list said nothing was running. Developer Mode was on, the bundle was installed, and the only fix was a rebuild, a framework strip, a re-sign with the right team and a reinstall.

Apple shipped iOS 26.6.1 on 17 August 2026, a security release with 29 CVEs fixed. Our benchmark phone took it overnight. The next morning xcrun devicectl device process launch reported success, the automation runner appeared on the phone, the process was gone from the process list seconds later, port 8100 refused connections, and iOS wrote no crash report. Developer Mode was still enabled and the app was still installed, so every check we had passed. The runner is built against the OS build, not the OS version, and a point release is enough to invalidate it.

Abstract technical illustration of a bridge whose far anchor has shifted by a few millimetres overnight, leaving the span visually intact but carrying nothing

Every instrument reading was green

The reason this took a morning rather than a minute is that nothing reported an error. A launch that reports success and then exits produces the same observable state as a launch that never happened, minus the error message that would tell you which.

what we checkedwhat it reportedwhat was truesource
devicectl device process launchsuccess, with a pidthe process was not there seconds laterFINDINGS s.11
the phone's screenAutomationModeUI startedit started and went awayFINDINGS s.11
the process listno WebDriverAgentcorrect, and the only true signalFINDINGS s.11
curl localhost:8100/statusconnection refusedcorrect, and the symptom we started fromFINDINGS s.11
crash reports on the devicenone writtenno crash report was generated at allFINDINGS s.11
Developer Modeenabledtrue, and irrelevantphoneshell/device.py
the runner bundle on the phoneinstalledtrue, and irrelevant: it was built against the previous OS buildphoneshell/device.py
WebDriverAgent release notes, 30 Aug to 11 Sep 2026ten releases, v16.11.4 to v16.12.8none of them mention iOS build coupling, because it is not their layerGitHub releases

Only two of those eight readings were informative, and both of them are downstream symptoms rather than causes. Nothing anywhere said "the runner is stale".

What a stale runner looks like from the Mac devicectl launch reports success + pid AutomationModeUI appears on the phone process exits no crash report port 8100 refused the only symptom you see meanwhile, every health check passes Developer Mode: on developer image: mounted runner bundle: installed WDA source: current the fact none of them carries: the bundle was built against iOS 26.6, the phone now runs 26.6.1 remedy: xcodebuild build-for-testing → remove embedded XC*.framework → codesign --force with the team's identity → install → launch our harness allows the xcodebuild step up to 1800 seconds; none of it can run while the phone sits at the lock screen after a reboot iOS 26.6.1 shipped 17 August 2026 with 29 CVEs fixed. phoneshell FINDINGS.md section 11.
The software on both sides was unchanged. The only thing that moved overnight was the operating system build number, and it was enough.

The repair has a trap in it

The rebuild is four steps, and the second and third exist because of two separate iOS behaviours that produce unhelpful errors.

The runner must not carry its own copy of XCTest. testmanagerd was renamed in iOS 17, embedded frameworks bind to the old name, and the bundle has to link the device's copies instead. The failure without this is a generic launch error that says nothing about frameworks. So the build is followed by deleting everything matching XC* plus Testing.framework and libXCTestSwiftSupport.dylib from the bundle's Frameworks directory, and then a re-sign, because deleting a file from a signed bundle invalidates the signature.

The re-sign is where the second trap sits. A Mac with two Apple signing teams in its keychain will happily build with whichever identity sorts first, and iOS then refuses the install over the existing app with IXUserPresentableErrorDomain error 1. That error's text says nothing about teams. An installed app cannot be replaced by a build from a different team, and the only way to know that is to already know it.

Rebuild, and the one place two signing teams break it 1. build build-for-testing DEVELOPMENT_TEAM=... CODE_SIGN_STYLE=Automatic 2. strip rm Frameworks/XC* Testing.framework signature now invalid 3. re-sign codesign --force --sign <identity sha1> --preserve-metadata 4. install over the existing app then launch detached team mismatch with the installed copy IXUserPresentableErrorDomain error 1 the message never mentions teams, certificates or signing the rule that avoids it never let the build pick an identity from the keychain order. Pin the team; refuse to guess when there are two. Automatic signing rejects an explicit identity hash with "conflicting provisioning settings", so the team id does the disambiguating during the build, and the SHA-1 is used only for the re-sign after the strip. phoneshell/device.py.
Two teams in one keychain is a normal state for a contractor's Mac. The build gives no warning, and the error arrives one step later in a different vocabulary.

What this says about running a phone rig continuously

The runner is a build artifact, not an app. Every guide treats installing WebDriverAgent as a setup step you do once, and for a test suite run from a developer's Mac that is true, because the developer notices the failure and rebuilds. For an unattended rig it is false in a way that costs a night: the phone updates itself, the artifact stops matching, and the rig reports a network error.

Two things follow. The rebuild has to be part of the runtime rather than the setup, triggered by the symptom rather than by a person. And the health check that decides whether the rig is alive cannot be the launcher's exit code, because that is exactly the reading that was wrong here. It has to be a request to port 8100 that comes back with a body.

Our own gap, stated plainly: the doctor checks Xcode, the device, Developer Mode, the developer image, the runner bundle, the launch and the port, and it does not compare the OS build the bundle was built against with the build now on the phone. That comparison is the check that would have named this failure in one line, and we have not written it yet.

A judgement, marked as one: a device rig should treat the OS build string as a dependency version and rebuild on change, in the same way a lockfile change triggers a reinstall. Nothing in the toolchain does this for you, and WebDriverAgent shipping ten releases in thirteen days (v16.11.4 on 30 August 2026 through v16.12.8 on 11 September 2026) means the client side moves too, so the version pair is what has to be recorded next to every benchmark result.

Check it yourself

You do not need our harness for any of this. The diagnostic is three commands, and the important one is the third, because it is the one that disagrees with the first.

# what the phone is running now
xcrun devicectl list devices
xcrun devicectl device info details --device <udid> | grep -i -E 'osVersion|buildVersion'

# launch the runner and believe nothing
xcrun devicectl device process launch --device <udid> --start-stopped=false \
  com.facebook.WebDriverAgentRunner.xctrunner
xcrun devicectl device info processes --device <udid> | grep -i webdriver   # the true answer
curl -s -m 3 localhost:8100/status || echo "port 8100 refused"

# how many signing teams this Mac has, which decides whether a rebuild can succeed at all
security find-identity -v -p codesigning

# our build path, including the strip and the re-sign
grep -n "def build_wda" -A 45 phoneshell/device.py
grep -n "def strip_xctest_frameworks" -A 20 phoneshell/device.py

To see the failure itself you need a phone that has just taken a point release, which is the one part that cannot be arranged on demand. Apple's security note for iOS 26.6.1 is at support.apple.com/en-us/148282, and the release went out on 17 August 2026.

What would prove this wrong

Sources

  1. Apple, About the security content of iOS 26.6.1 and iPadOS 26.6.1, 17 August 2026. https://support.apple.com/en-us/148282
  2. MacRumors, iOS 26.6.1 and macOS Tahoe 26.6.2 fix nearly 30 security vulnerabilities, 17 August 2026. https://www.macrumors.com/2026/08/17/ios-26-6-1-security-fixes/
  3. Appium WebDriverAgent releases, v16.11.4 on 30 August 2026 through v16.12.8 on 11 September 2026. https://github.com/appium/WebDriverAgent/releases
  4. Appium XCUITest driver, real device configuration, signing and provisioning. https://appium.github.io/appium-xcuitest-driver/latest/preparation/real-device-config/
  5. phoneshell, FINDINGS.md section 11, and phoneshell/device.py: build_wda, strip_xctest_frameworks and detect_team. https://github.com/Blomega/phoneshell/blob/main/phoneshell/device.py