From eae23bc9c015f63167c21849519f46d658e10b7d Mon Sep 17 00:00:00 2001 From: Pietro Di Bello Date: Sat, 18 Jul 2026 23:39:26 +0200 Subject: [PATCH] fix(warp): stop /dev/tty ENXIO error leaking to the user 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. --- plugins/warp/scripts/emit-terminal-sequence.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/warp/scripts/emit-terminal-sequence.sh b/plugins/warp/scripts/emit-terminal-sequence.sh index b6a83b9..80a207e 100644 --- a/plugins/warp/scripts/emit-terminal-sequence.sh +++ b/plugins/warp/scripts/emit-terminal-sequence.sh @@ -72,14 +72,24 @@ emit_terminal_sequence() { # Known-old Claude Code — /dev/tty is the only safe path. # Emitting terminalSequence here would be rejected by the Stop # hook validator as an unknown field. - printf '%s' "$seq" > /dev/tty 2>/dev/null || true + # + # The write is wrapped in a brace group before the redirect to + # /dev/null: when there's no controlling terminal, opening + # /dev/tty fails with ENXIO ("Device not configured") and bash + # reports that itself, to the *original* stderr — a bare + # `> /dev/tty 2>/dev/null` can't catch it because the failing + # redirect is set up before the `2>/dev/null` one. Grouping + # applies 2>/dev/null to the whole group first. + { printf '%s' "$seq" > /dev/tty; } 2>/dev/null || true fi return 0 fi # Unknown Claude Code version — try /dev/tty, fall back to JSON # as a best-effort attempt for new CC without version detection. - if printf '%s' "$seq" > /dev/tty 2>/dev/null; then + # See the brace-group note above: it's needed here too, otherwise a + # missing controlling terminal leaks a raw bash error to the user. + if { printf '%s' "$seq" > /dev/tty; } 2>/dev/null; then return 0 fi jq -nc --arg seq "$seq" '{terminalSequence: $seq}'