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.
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 checked | what it reported | what was true | source |
|---|---|---|---|
devicectl device process launch | success, with a pid | the process was not there seconds later | FINDINGS s.11 |
| the phone's screen | AutomationModeUI started | it started and went away | FINDINGS s.11 |
| the process list | no WebDriverAgent | correct, and the only true signal | FINDINGS s.11 |
curl localhost:8100/status | connection refused | correct, and the symptom we started from | FINDINGS s.11 |
| crash reports on the device | none written | no crash report was generated at all | FINDINGS s.11 |
| Developer Mode | enabled | true, and irrelevant | phoneshell/device.py |
| the runner bundle on the phone | installed | true, and irrelevant: it was built against the previous OS build | phoneshell/device.py |
| WebDriverAgent release notes, 30 Aug to 11 Sep 2026 | ten releases, v16.11.4 to v16.12.8 | none of them mention iOS build coupling, because it is not their layer | GitHub 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".
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.
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
- Take a phone through the next iOS point release with a runner built against the previous build, and have it keep working. That would mean the coupling is to the major version rather than the build, and our reading of this incident is wrong. We predict a rebuild will be required on the next 26.x point release, through 30 June 2027.
- Reinstall the same unmodified bundle, without rebuilding, and have the runner stay up. That would mean the failure was install-state corruption rather than staleness, which is a different and cheaper problem.
- The claim we are least sure of: that no crash report was generated. Absence of evidence on a device where crash reporting is itself a service is weak. If you can reproduce this and find a report under Analytics Data, the exit had a cause we never saw, and the diagnosis above is a correlation.
Sources
- 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
- 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/
- Appium WebDriverAgent releases, v16.11.4 on 30 August 2026 through v16.12.8 on 11 September 2026. https://github.com/appium/WebDriverAgent/releases
- Appium XCUITest driver, real device configuration, signing and provisioning. https://appium.github.io/appium-xcuitest-driver/latest/preparation/real-device-config/
- 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