[BUG] Session crash/freeze from Bash output containing many carriage returns (\r) — tail -100 silently returns 4.4MB

Resolved 💬 3 comments Opened Feb 6, 2026 by miyamamoto Closed Feb 9, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code crashes or freezes when a Bash tool command returns output containing a large number of \r (carriage return, 0x0D) characters. The typical scenario is reading log files that contain tqdm progress bar output.

The key insight: tail -100 counts lines by \n (newline), but tqdm progress bars update using \r (carriage return) without \n. This means a single "line" in the log file contains thousands of \r-separated progress updates. \tail -100\ appears to request just 100 lines, but actually returns megabytes of data.

In our case:

  • tail -100 logfile.log returned 4,439,692 bytes (4.4 MB)
  • The output contained 41,208 \r characters and zero ANSI escape codes
  • The log file itself was 4.6 MB with only 3,029 \n-delimited lines
  • Average bytes per line: ~1,518 bytes (due to \r-packed tqdm output)

The session crashes/restarts immediately with no error message. This was 100% reproducible across 4 consecutive session attempts.

What Should Happen?

Claude Code should handle large Bash output gracefully:

  1. Truncate by byte count, not just line count — the existing 30,000-character truncation should prevent multi-MB output from reaching the session
  2. Strip or collapse \r-separated segments before storing in session history — only the final segment after the last \r on each line is visually meaningful
  3. At minimum, fail gracefully with a warning instead of crashing the session

Error Messages/Logs

No error message. The session silently crashes and shows "Session Restarted":

● Bash(ssh 192.168.0.220 "tail -100 /home/keiba/keiba/logs/initial_setup_20260205_193410.log")
  ⎿  Running PreToolUse hook…
  ⎿  Running…

✻ Computing…

──────────────────────────────────────────────────────────────────────────────────────────
 Session Restarted

Steps to Reproduce

  1. Create a log file with tqdm progress bar output:
python3 -c "
from tqdm import tqdm
import time, sys
for i in tqdm(range(10000), file=sys.stdout):
    time.sleep(0.001)
" > /tmp/tqdm_test.log 2>&1
  1. Verify the file has many \r characters but few \n:
wc -l /tmp/tqdm_test.log          # Few lines (newlines)
wc -c /tmp/tqdm_test.log          # Large byte count
cat /tmp/tqdm_test.log | tr -cd '\r' | wc -c  # Many carriage returns
  1. In Claude Code, run:
tail -100 /tmp/tqdm_test.log
  1. Session freezes or crashes.

Our actual scenario: Reading a remote log file via SSH where initial_setup.sh runs make-features with tqdm progress bars processing 29,128 races. The log accumulated 41,208 \r characters over 6+ hours of processing.

Root Cause Analysis

The issue is specifically about \r (0x0D) characters:

| Metric | Value |
|--------|-------|
| File size | 4.6 MB |
| Lines (\n count) | 3,029 |
| Carriage returns (\r) | 41,208 |
| ANSI escape codes | 0 |
| tail -100 output size | 4.4 MB |
| Average bytes per \n-line | 1,518 |

The Bash tool's 30,000-character truncation limit should prevent this, but it appears the full output is being processed before truncation occurs, or the truncation is not applied in all code paths.

Suggested Fix

Option A (minimal): Before storing Bash output in session state, collapse \r-separated content:

// For each line in output, only keep content after the last \r
output = output.split('\n').map(line => {
  const parts = line.split('\r');
  return parts[parts.length - 1];
}).join('\n');

This would reduce the 4.4 MB output to ~12 KB (100 lines × ~120 chars), which is the actual meaningful content.

Option B (robust): Enforce byte-based truncation limits before any processing, not just character/line-based limits.

Related Issues

  • #18095 — Session freezes when reading persisted-output tool-results file after large Bash output
  • #21179 — Unbounded session file growth from verbose command output causes 100% CPU + OOM crash
  • #21022 — Claude Code hangs when accessing large session files (>50MB)
  • #20470 — Large base64 data in transcripts causes crash on startup

This issue adds a new dimension: seemingly small commands (tail -100) can produce unexpectedly massive output due to \r characters, making the root cause very difficult for users to diagnose.

Workaround

Strip carriage returns when reading tqdm/progress-bar log files:

tail -100 logfile.log | tr -d '\r'
# or limit by bytes:
tail -c 5000 logfile.log | tr -d '\r'

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.32

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux (22.04.5 LTS, kernel 6.8.0-90-generic)

Terminal/Shell

SSH terminal (Mac → Ubuntu server → Claude Code → SSH → remote server)

Additional Information

  • The crash is 100% reproducible with tqdm log files
  • The same tail command works fine in a normal shell — the issue is Claude Code's output handling
  • Simple SSH commands to the same server work fine (e.g., ps aux | grep ... returns small output)
  • PreToolUse/PostToolUse hooks are NOT the cause (verified by analyzing matcher rules)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗