Claude attempts Read(/dev/stdin) on pasted content, causing infinite hang
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
- Start a Claude Code session
- Paste multi-line content (code, logs, or text)
- Claude occasionally interprets this as "read from a file at stdin"
- Claude calls
Read(/dev/stdin) - 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:
- Reject invalid paths:
/dev/stdin,/dev/fd/*,/proc/self/fd/*should be rejected as invalid file targets - AI training: The model should be trained/prompted to never attempt reading from stdin
- 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.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗