Skip to content

Comments

[pull] main from expo:main#615

Merged
pull[bot] merged 2 commits intocode:mainfrom
expo:main
Feb 21, 2026
Merged

[pull] main from expo:main#615
pull[bot] merged 2 commits intocode:mainfrom
expo:main

Conversation

@pull
Copy link

@pull pull bot commented Feb 21, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

axeelz and others added 2 commits February 21, 2026 19:26
)

# Why

When installing an app onto a physical iOS device, Apple's xcrun
devicectl tool frequently drops the connection immediately after the
initial handshake, throwing com.apple.dt.CoreDeviceError error 4000
(0xFA0).

Because @expo/cli currently reads stderr synchronously on the process
close event (childProcess.stderr.read()), this error is often swallowed
if the stream is already flushed. This results in an unhelpful Error:
null crash that leaves developers confused and without any actionable
debugging information. Furthermore, the lack of a retry mechanism means
these transient network/USB disconnects strictly fail the build every
time.

# How

1. Fixed `Error: null` masking: Replaced the synchronous stderr.read()
call with an asynchronous stderr.on('data', ...) buffer accumulator to
reliably capture and surface the true error output from the Apple
toolchain.
2. Added Exponential Backoff: Wrapped the devicectl spawn logic in an
exponential backoff retry loop (up to 3 attempts).
3. Targeted Retries: The retry loop strictly checks the error message
and only intercepts transient disconnect errors (CoreDeviceError /
0xFA0). All other deterministic errors fail immediately.
4. Preserved Cancellation: Explicitly catches error.code === 'detached'
to ensure that user cancellations (e.g., pressing Ctrl+C) immediately
abort the process instead of trapping the developer in the retry loop.
5. Preserved UX: Maintained the asynchronous spawn approach and standard
IO parsing so the CLI ora spinner and 34%... progress updates remain
fully functional.

# Test Plan

- Ran npx expo run:ios --device <uuid> targeting a physical iPhone via
USB.
- Before: Observed an immediate CLI crash outputting Error: null.
- After (Error surfacing): Verified that the CLI successfully captures
and prints the underlying CoreDeviceError error 4000 (0xFA0).
- After (Retry Logic): Verified that the CLI catches the transient
error, waits 2 seconds, updates the ora spinner to Installing (attempt
2), and successfully installs the app on the second attempt without
breaking the event loop.
- Cancellation: Verified that pressing Ctrl+C during an installation
attempt successfully and immediately aborts the process.

# Checklist

- [X] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [X] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

---------

Co-authored-by: Phil Pluckthun <phil@kitten.sh>
@pull pull bot locked and limited conversation to collaborators Feb 21, 2026
@pull pull bot added the ⤵️ pull label Feb 21, 2026
@pull pull bot merged commit bc2b1f4 into code:main Feb 21, 2026
3 of 4 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants