-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Bug
The terminal tool (run_in_terminal) corrupts any multiline command exceeding 1024 bytes. After byte 1024, content wraps around and replays earlier buffer content, destroying the remainder of the command and leaving the shell stuck in quote> or heredoc> mode.
Minimal Reproduction
Ask Copilot to run this in the terminal (19 lines × 55 chars + wrapper = 1077 bytes):
echo 'L01 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L02 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L03 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L04 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L05 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L06 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L07 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L08 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L09 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L11 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L12 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L13 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L14 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L15 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L16 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L17 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L18 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L19 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' | wc -c
Expected: Outputs 1064
Actual: L19 becomes garbled (L19 aaaaaL02 aaa...), closing ' is lost, shell stuck at quote>
Reduce to 18 lines (1021 bytes) → works perfectly. The boundary is exactly 1024 bytes.
Verified Facts
| Test case | Result |
|---|---|
| 18 lines × 55 chars (1021 bytes), multiline | ✅ Works |
| 19 lines × 55 chars (1077 bytes), multiline | ❌ Corrupts at byte 1024 |
Same 20-line content via $'...\n...' (1156 bytes, single-line) |
✅ Works |
| Single line of 2000+ chars | ✅ Works |
cat << 'EOF' heredoc > 1024 bytes |
❌ Corrupts at byte 1024 |
python3 -c "..." multiline > 1024 bytes |
❌ Corrupts at byte 1024 |
The corruption only affects multiline commands (containing literal newline characters) and always occurs at exactly byte 1024.
Why This Is a Serious Problem
The failure mode is cascading and difficult to recover from:
-
Silent corruption: The tool reports success ("The tool simplified the command to...") but the shell receives garbled data. The agent has no way to detect this before it happens.
-
Shell gets permanently stuck: The closing delimiter (
',",EOF) is lost in the corruption, so the shell entersquote>orheredoc>mode. Every subsequent command the agent sends is swallowed as continuation of the broken quote — the terminal is bricked until a new one is opened. -
Extremely common trigger: 1024 bytes is a very low threshold. Any of these routine operations can exceed it:
gh issue create --body '...'orgh pr create --body '...'with a detailed description- Heredoc writes (
cat > file << 'EOF') - Inline Python/Node scripts (
python3 -c "...") - Any multiline shell script pasted to the terminal
-
Hard to diagnose: The garbled output looks like random gibberish — fragments of earlier content mixed with later content. Without knowing about the 1024-byte boundary, this appears to be a non-deterministic, unreproducible glitch. (We initially filed and closed a report as "unreproducible" before discovering the byte-count trigger.)
-
Recovery makes things worse: When the agent sees an error or stuck shell, it typically retries. But the terminal is stuck in quote mode, so retries just feed more text into the broken quote, creating increasingly bizarre output and wasting tokens.
Root Cause Hypothesis
The terminal tool uses a different input mechanism for multiline commands (likely bracketed paste or line-by-line writing to the PTY) compared to single-line commands. This multiline path appears to use a 1024-byte buffer — a classic PIPE_BUF or PTY canonical-mode buffer size — that wraps on overflow rather than flushing and continuing.
Environment
- VS Code Insiders
- macOS
- zsh
- Copilot agent mode (Claude)