fix(cli): exit cleanly on terminal hangup (read EIO) during interactive prompts#650
Merged
Conversation
…ve prompts Guard process.stdin with an error handler so a vanished terminal/PTY (closed tab, dropped SSH/tmux session, sleep/wake) that raises `read EIO` on the raw-mode stdin handle exits cleanly (code 129) instead of crashing as a fatal uncaught exception and reporting to Sentry. Non-hangup stdin errors are re-thrown, preserving existing crash reporting. Co-authored-by: Cursor <cursoragent@cursor.com>
|
✅ Parity OK — no diagnostic differences. Baseline:
trace |
Align the guardStdin() call-site comment with the adjacent stdout EPIPE handler (same class of Node stream-error workaround), per the repo's "// HACK:" convention. Co-authored-by: Cursor <cursoragent@cursor.com>
commit: |
Extract the duplicated process.exit stub into a named helper and remove the unused `syscall` field from the fake stdin error (handleStdinError only reads `code`). Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # packages/react-doctor/src/cli/index.ts
Contributor
|
React Doctor found 5 files changed in this pull request, but none matched the files covered by its enabled checks. Scope: 5 files changed on Generated by React Doctor. Questions? Contact founders@million.dev. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Catches the
Error: read EIOcrash reported in Sentry (REACT-DOCTOR-S).The only thing that reads stdin is the interactive
promptsUI (e.g. the multiselect "Select projects" prompt in a monorepo), which opens the TTY in raw mode and never attaches an'error'listener. When the terminal/PTY backing that prompt goes away mid-read — closing the tab, the parent shell exiting, a dropped SSH/tmux/screen session, or the machine sleeping/waking — the nextread()returnsEIO. With no listener onprocess.stdin, Node escalates that stream error into a fatal uncaught exception, which the Sentryonuncaughtexceptionintegration reports as a crash (level: fatal,handled: no). The stack is pure Node internals (TTY.onStreamRead), confirming an environmental terminal teardown rather than a logic bug.Before (no stdin error listener — an environmental hangup crashes and is reported to Sentry):
After (stdin is guarded; a hangup exits cleanly, genuine errors still report):
What changed
guardStdin()(src/cli/utils/guard-stdin.ts), armed at startup incli/index.tsnext tounrefStdin()and the existing stdout EPIPE guard it mirrors.errno(EIO/ENXIO) the CLI exits cleanly with code129(POSIX128 + SIGHUP), so the run ends like an interruption instead of a crash.TERMINAL_HANGUP_EXIT_CODE = 129toconstants.ts, alongside the existingSIGINT_EXIT_CODE.EIO/ENXIO, re-throws (never exits) onEPIPE/EACCES/no-code, and thatguardStdin()registers the handler.Eval results
RDE not run — this is a CLI stdin/teardown fix, not a lint rule, so the rule-eval harness doesn't apply.
Test plan
pnpm test(react-doctor) — 170 passed, incl. newtests/guard-stdin.test.tspnpm typecheck— cleanpnpm format:check— clean;pnpm lint— clean (only pre-existing fixture warnings)Made with Cursor
Note
Low Risk
Small, startup-only stdin listener with narrow errno handling; non-hangup errors unchanged; covered by unit tests.
Overview
Adds a startup stdin error guard (parallel to the existing stdout
EPIPEhandler) so losing the TTY while an interactivepromptsread is in progress no longer becomes a fatal uncaughtread EIO/ Sentry crash.guardStdin()wiresprocess.stdin'error'tohandleStdinError:EIO/ENXIO→process.exit(129)via newTERMINAL_HANGUP_EXIT_CODE; any other code is re-thrown so real stdin failures still hit the crash reporter.guardStdin()is invoked fromcli/index.tsright afterunrefStdin(), before commands run. Tests cover hangup vs non-hangup errno and listener registration; changeset documents the patch.Reviewed by Cursor Bugbot for commit 134f305. Bugbot is set up for automated code reviews on this repo. Configure here.