fix(ios): diagnose a runner that cannot install, instead of blaming the screen - #1529
Conversation
…he screen A physical device that is not covered by the runner's provisioning profile fails to install the XCTest runner. Every runner-backed command then failed with 'the current screen is overwhelming the iOS accessibility capture' and advice to run screenshot instead — which fails identically, because it needs the same runner. The suggested remedy could never work and the stated cause was never observed. Classify the install failure and say what it is: the profile does not cover this device, register it with the signing team. It is deliberately not an infrastructure reason, because no retry registers a device. Matching anchors on the CoreDevice error code and the English framework strings; the installer prose around them is localized by macOS, so the real log arrived partly in Polish. The recycle-budget error also stops asserting a cause it never observed. It now points at the runner log first and offers the heavy-screen reading second, which is where it belongs — that case is real, it just is not the only one. Observed on an iPhone that could not be added to the signing account.
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
|
Reviewed exact head 4b01003. One blocking production-route issue remains: P1 — the early-exit error still discards the new provisioning hint. buildRunnerEarlyExitError correctly computes IOS_RUNNER_DEVICE_NOT_PROVISIONED, but constructs details.hint through resolveRunnerEarlyExitHint, whose fallback always returns connect-timeout/cache-recovery guidance. For the captured xcodebuild failure, users are therefore still told to retry runner startup rather than register the device—the misdiagnosis this PR intends to fix. Thread the classified reason into the hint selection (preserving the busy-device special case) and add a regression test against buildRunnerEarlyExitError that asserts the reason/hint pair on the real captured output. CI is green and the PR is mergeable, but this blocks readiness. The unavailable device prevents a repeat live run; the captured hardware log is acceptable residual evidence once the production route is covered. |
buildRunnerEarlyExitError classified the provisioning failure correctly, then built its hint through resolveRunnerEarlyExitHint, which ignored the reason and always fell back to connect-timeout and cache-recovery guidance. The shipped error therefore still told people to retry a runner that can never install, which is the misdiagnosis the previous commit set out to remove. Thread the reason through, keeping the busy-connecting device special case, and withhold the cache-recovery sentence for a provisioning failure: clearing derived data cannot put a device into a profile. The previous commit only tested classifyBootFailure and bootFailureHint, never the function that assembles the error a user receives. The regression added here exercises that production route on the captured xcodebuild output.
|
Fixed at
Why I missed it: the previous commit tested Change: the classified reason is threaded into Regression is against the production route, as you asked: Two guard tests came with it, so the fix cannot quietly swallow the other paths: an ordinary early exit still gets connect-timeout and cache-recovery guidance, and a busy connecting device keeps its own targeted hint. 482 tests green across the Apple core suites and boot-diagnostics; lint and typecheck clean. |
|
Re-reviewed exact head P1 — the new device-not-provisioned classifier matches generic signing failures. CI is still running on this head, so no readiness label yet. |
|
Addressed in 36c19be. The device-not-provisioned diagnosis now requires CoreDevice code Validation: |
|
Second messaging fix from the #1521 hardware run, and the worse of the two: this one confidently states a cause that was never observed and recommends a remedy that cannot work.
What a user sees today
A physical iPhone that is not covered by the runner's provisioning profile cannot install the XCTest runner.
openstill succeeds — a CoreDevice app launch goes throughdevicectland needs no runner — so the session looks healthy. Then every runner-backed command fails with:Both halves are wrong here:
screenshotis offered as the escape hatch, but on a physical device it needs the same runner, so it fails identicallyThe truth was sitting in the runner log the whole time:
I lost several minutes to "heavy Settings screen" before reading that log. Someone without log access loses far more, and no amount of retrying or screen-changing will ever help.
Change
Classify it. New
IOS_RUNNER_DEVICE_NOT_PROVISIONEDboot-failure reason, matched before the connect-timeout branch — a runner that cannot install also never accepts a connection, so the timeout reading would win and send people to look at the screen or the network instead of the signing account. The hint names the fix: register the device with the signing team, and notes that retrying will keep failing.Deliberately not an infrastructure reason: infrastructure reasons imply a retryable environment blip, and no retry registers a device.
Stop asserting. The recycle-budget error only ever knows that a restart was already spent, never why. It now points at the runner log first and offers the heavy-screen reading second. That case is real — it just is not the only one, and it was being stated as fact.
A matching detail worth knowing
The real log came back partly in Polish (
Nie można zainstalować…), because macOS localizes the installer prose. Matching therefore anchors only on the CoreDevice error code0xe8008012and the English framework strings (provisioning profile,embedded profile). The test uses the captured output verbatim, localized text included, so this stays honest.Testing
IOS_RUNNER_CONNECT_TIMEOUT, so the new branch does not swallow itThe device that produced this has since been unpaired, so there is no live re-run — the evidence is the captured log, which the test asserts against directly.
check:affectedshows provider-integration/daemon-entrypoint timeouts whose failing set differs on every run (7, then 3) with zero assertion failures, and all pass in isolation — the known contention signature on a host that has been driving devices for hours. Nothing in that set touches boot-diagnostics or the recycle ledger.Follows #1527, which fixed the same class of misdiagnosis for Developer Mode and pairing.
Closes #1521 — its remaining item (two fully-live sessions) is blocked by a device that cannot join the signing account, not by an open engineering question. Full evidence for every other leg is in that issue.