Skip to content

fix(ios): map usbmux connect result codes to the right verdict - #1523

Merged
thymikee merged 1 commit into
mainfrom
fix/usbmux-connect-result-codes
Jul 31, 2026
Merged

fix(ios): map usbmux connect result codes to the right verdict#1523
thymikee merged 1 commit into
mainfrom
fix/usbmux-connect-result-codes

Conversation

@thymikee

Copy link
Copy Markdown
Member

Tackles the verifiable half of #1521, and closes a gap #1517 left open.

The gap

usbmuxd answers Connect with a result code, and every non-zero code collapsed into a single error with a cable hint:

Failed to connect to XCTest runner through usbmux
hint: Keep the device connected by cable and unlocked, then retry.

I probed the daemon on this host rather than trusting documentation, using the real cabled iPhone:

Connect -> real device, closed port  => Number = 3
Connect -> bogus DeviceID            => Number = 2

Result 2 (device gone) never reached the fallback. #1517 keys its tunnel fallback off usbmuxDeviceAttached: false, which only the ListDevices path set. If a device disappears between ListDevices and Connect, a CoreDevice device failed with a cable hint while its Wi-Fi tunnel was sitting there working. It now raises the same unattached verdict, so the fallback runs.

Result 3 (port not bound) got the wrong advice. The cable is fine and the device is unlocked — the runner just is not listening yet, which is the normal state while it starts. It now says that instead of blaming the cable.

#1521 coverage

The live two-device matrix still needs a second iPhone, but the substance of "is UDID→device selection unambiguous" is now locked down hermetically against the fake usbmuxd:

  • selection follows the UDID, not list position — asserted with the target first, last, and in the middle, checking the DeviceID actually sent in Connect
  • a device whose UDID merely shares a prefix with the requested one never matches, and no Connect is attempted
  • device-gone and port-refused each produce their own verdict
  • transport-level: a mid-connect device loss on a CoreDevice device reaches the tunnel and succeeds

Both result-code tests were verified revert-sensitive — restoring the collapsed handler fails them.

Remaining in #1521

Two concurrent sessions on two cabled devices, and the unpaired/untrusted legs. Those still need hardware; I have updated #1521 rather than closing it.

pnpm check:affected --run passes.

usbmuxd answers Connect with a result code, and every non-zero code collapsed
into one 'Failed to connect' error carrying a cable hint. Probing the daemon on
this host for the two codes that matter: an unknown DeviceID answers 2, and a
closed port on an attached device answers 3.

Result 2 means the device went away between ListDevices and Connect. It now
raises the same unattached verdict as a missing ListDevices entry, so a
CoreDevice device falls back to its network tunnel instead of failing with a
cable hint while Wi-Fi is available — the gap #1517 left open.

Result 3 means the device is reachable and only the runner port is not bound
yet, which is the normal state while the runner starts. Telling the user to
check the cable was wrong; it now says so.

Adds hermetic multi-device coverage for #1521: selection follows the UDID
rather than list position, and a UDID sharing a prefix with another device
never matches.
@github-actions

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.91 MB 1.91 MB +538 B
JS gzip 612.9 kB 613.1 kB +165 B
npm tarball 730.5 kB 730.7 kB +174 B
npm unpacked 2.56 MB 2.56 MB +538 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.2 ms 26.7 ms +0.5 ms
CLI --help 56.3 ms 56.5 ms +0.3 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/runner-disposal.js +538 B +165 B

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Jul 31, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Clean review at b9bf3b9c2bdef8fbb6977fd453fe8091c8790cf7. A mid-connect usbmux BadDevice result now takes the same typed unattached path as a missing device-list entry, so CoreDevice devices reach the existing tunnel fallback without spending a retry; a refused runner port remains a retryable startup condition with a truthful hint. The UDID-selection, result-code, and fallback regressions are non-vacuous, and exact-head CI is green.

Residual risk: #1521’s real multi-device and unpaired/untrusted hardware matrix remains open; no separately authorized cross-vendor review was performed.

@thymikee
thymikee merged commit 6b972ae into main Jul 31, 2026
30 checks passed
@thymikee
thymikee deleted the fix/usbmux-connect-result-codes branch July 31, 2026 10:30
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-31 10:31 UTC

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

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant