Claude attempts Read(/dev/stdin) on pasted content, causing infinite hang

Resolved 💬 5 comments Opened Dec 17, 2025 by KCW89 Closed Feb 14, 2026

Description

When pasting multi-line content into Claude Code, the AI model sometimes decides to call Read(/dev/stdin) instead of recognizing that the pasted content is already available in the conversation context. This causes an infinite hang.

Environment

  • Claude Code Version: Latest (Dec 2025)
  • OS: macOS 14.x (Darwin 24.5.0)
  • Node.js: v20+

Steps to Reproduce

  1. Start a Claude Code session
  2. Paste multi-line content (code, logs, or text)
  3. Claude occasionally interprets this as "read from a file at stdin"
  4. Claude calls Read(/dev/stdin)
  5. Session hangs forever on "Wibbling..." with no way to recover except Ctrl+C

Expected Behavior

Claude should recognize that pasted content is already present in the conversation message and use it directly, never attempting to read from /dev/stdin.

Actual Behavior

Claude calls Read(/dev/stdin), which blocks indefinitely waiting for EOF that never comes (since the IPC pipe stays open).

⏺ Read(/dev/stdin)
  · Wibbling… (esc to interrupt · thinking)

The session becomes completely unresponsive.

Root Cause Analysis

| Factor | Explanation |
|--------|-------------|
| /dev/stdin is a character device | Blocks on read() until EOF |
| Claude Code's IPC pipe | Doesn't close, so EOF never arrives |
| Result | Read tool hangs forever waiting for input |

Why This Happens

The AI model sometimes misinterprets pasted content as a file reference and attempts to read it. For example:

User pastes:
"Here's my code:
def foo():
    pass"

Claude thinks: "I should read this file" → Read(/dev/stdin) → HANG

Workaround (PreToolUse Hook)

Add a PreToolUse hook to block dangerous Read paths:

# ~/.claude/hooks/pretool_validation.py

def validate_read_operation(file_path: str) -> tuple:
    """Block Read operations on stdin-like paths that hang forever."""
    dangerous_paths = ['/dev/stdin', '/dev/fd/0', '/proc/self/fd/0']
    if any(file_path == p or file_path.startswith(p) for p in dangerous_paths):
        return (False, "❌ BLOCKED: Read(/dev/stdin) hangs forever. Pasted content is already in the message.")
    return (True, None)

# In main():
if tool_name == 'Read':
    file_path = params.get('file_path', '')
    allow, message = validate_read_operation(file_path)
    if not allow:
        output_json({"allow": False, "message": message})
        return 1

Suggested Fix

The Read tool itself (or the AI's decision layer) should:

  1. Reject invalid paths: /dev/stdin, /dev/fd/*, /proc/self/fd/* should be rejected as invalid file targets
  2. AI training: The model should be trained/prompted to never attempt reading from stdin
  3. Timeout: Add a timeout to the Read tool so it doesn't hang indefinitely

Recommended Implementation

// In Read tool implementation
const BLOCKED_PATHS = ['/dev/stdin', '/dev/fd/0', '/proc/self/fd/0'];

if (BLOCKED_PATHS.some(p => filePath === p || filePath.startsWith(p))) {
  throw new Error('Cannot read from stdin - pasted content is already in the conversation');
}

Impact

  • Severity: Medium-High - causes complete session freeze
  • Workaround: Available (PreToolUse hook)
  • Frequency: Intermittent - depends on AI interpretation of pasted content

Related Issues

This is separate from #14124 (SQLite contention) but can compound hanging issues when multiple sessions are involved.

View original on GitHub ↗

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