Skip to content

fix(warp): stop /dev/tty ENXIO error leaking to the user#75

Open
xpepper wants to merge 1 commit into
warpdotdev:mainfrom
xpepper:fix/dev-tty-error-leak
Open

fix(warp): stop /dev/tty ENXIO error leaking to the user#75
xpepper wants to merge 1 commit into
warpdotdev:mainfrom
xpepper:fix/dev-tty-error-leak

Conversation

@xpepper

@xpepper xpepper commented Jul 18, 2026

Copy link
Copy Markdown

Summary

  • emit-terminal-sequence.sh writes to /dev/tty as a fallback when CLAUDE_CODE_VERSION can't be resolved (e.g. during SessionStart, before the version-detection env caching kicks in). When the hook subprocess has no controlling terminal, opening /dev/tty fails with ENXIO, and bash reports "line N: /dev/tty: Device not configured" itself — to the original stderr, before the script's own 2>/dev/null on that same command takes effect. The result is a raw bash error printed to the user on session start, even though the script goes on to correctly fall back to the terminalSequence JSON output.
  • Fix: wrap the write in a brace group before applying 2>/dev/null, so the suppression covers the whole group (including the redirect's own open failure) rather than trying to suppress errors on a redirect that fails before the following one applies.
  • No behavior change otherwise — return codes and the JSON fallback path are identical.

Repro

$ bash -c 'printf hi > /dev/tty 2>/dev/null'
bash: line 1: /dev/tty: Device not configured   # leaks despite 2>/dev/null

$ bash -c '{ printf hi > /dev/tty; } 2>/dev/null'
# (nothing — cleanly suppressed)

Before/after against this repo's emit_terminal_sequence, no controlling tty, unset CLAUDE_CODE_VERSION:

# before
./emit-terminal-sequence.sh: line 82: /dev/tty: Device not configured
{"terminalSequence":"test-seq"}

# after
{"terminalSequence":"test-seq"}

Test plan

  • plugins/warp/tests/test-hooks.sh: 57/57 passing, unchanged
  • Manual before/after repro (above) confirming the leaked error is gone and the JSON fallback output is unchanged

When there's no controlling terminal (e.g. a SessionStart hook
subprocess before CLAUDE_CODE_VERSION is resolvable), the /dev/tty
write fails with ENXIO. `> /dev/tty 2>/dev/null` can't suppress bash's
own "Device not configured" diagnostic in that case: bash reports the
failed redirect before it applies the following 2>/dev/null, so the
raw error still reaches the user's terminal on session start.

Wrapping the write in a brace group before the 2>/dev/null redirect
applies the suppression to the whole group up front, so the error is
caught. Behavior (return codes, JSON fallback) is unchanged; verified
against the existing test-hooks.sh suite (57/57 passing) plus a direct
before/after repro with no controlling tty and an unset
CLAUDE_CODE_VERSION.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant