[BUG] Hook callback errors (Stream closed) on every tool call when using Agent SDK with bypassPermissions

Resolved 💬 3 comments Opened Feb 6, 2026 by sebyx07 Closed Feb 10, 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?

When using the Claude Agent SDK (Python) with permission_mode="bypassPermissions", every single tool call produces a noisy Error in hook callback hook_0: Stream closed error. The error dumps ~50 lines of minified Bun CLI source code to stderr on each tool call, making logs unreadable.

The errors are non-fatal — all tools complete successfully — but a typical agent session with 20-30 tool calls generates thousands of lines of error noise.

This started with claude-agent-sdk>=0.1.29 which introduced new hook events (SubagentStop, Notification, PermissionRequest). The bundled Claude CLI (v2.1.31+) appears to fire these hook callbacks even in bypassPermissions mode, and the sendRequest call fails because the stream context is wrong.

Also filed on the Python SDK: https://github.com/anthropics/claude-agent-sdk-python/issues/554

Error Messages/Logs

Every tool call produces this (two consecutive calls shown):

[claude 10:58:16] Using tool: Read → CLAUDE.md
Error in hook callback hook_0: 6339 | Claude Code has been suspended. Run `fg` to bring Claude Code back.
6340 | Note: ctrl + z now suspends Claude Code, ctrl + _ undoes input.
6341 | `)},FL=()=>{l1((SL)=>SL+1)};return uI?.on("suspend",J$),uI?.on("resume",FL),()=>{
uI?.off("suspend",J$),uI?.off("resume",FL)}},[uI]);let Cf=lA.useMemo(()=>b5(eA).filter(at),
[eA]),kf=lA.useMemo(()=>{if(!ZA)return null;let J$=aL.filter((G9)=>G9.type==="progress"&&
G9.data.type==="hook_progress"&&(G9.data.hookEvent==="Stop"||G9.data.hookEvent==="SubagentStop"));
...truncated ~50 lines of minified source...
6344 | `)}async sendRequest(H,$,A){let L=HEB.randomUUID(),I={type:"control_request",request_id:L,
request:H};if(this.inputClosed)throw Error("Stream closed");

error: Stream closed
      at sendRequest (/$bunfs/root/claude:6344:133)
      at sendRequest (/$bunfs/root/claude:6344:627)
      at <anonymous> (/$bunfs/root/claude:6344:1305)
      at callback (/$bunfs/root/claude:6344:1451)
      at _U1 (/$bunfs/root/claude:3151:1288)
      at _U1 (/$bunfs/root/claude:3151:1525)
      at <anonymous> (/$bunfs/root/claude:3144:1239)
      at A (/$bunfs/root/claude:1240:1491)
      at MK$ (/$bunfs/root/claude:1240:1641)
      at iS (/$bunfs/root/claude:3144:5408)

[claude 10:58:16] Tool completed                    ← tool still succeeds

[claude 10:58:16] Using tool: Glob → *.{eslintrc,prettierrc,editorconfig} in .
Error in hook callback hook_0: 6339 | Claude Code has been suspended...
<exact same error block repeats>
[claude 10:58:16] Tool completed                    ← tool still succeeds

Steps to Reproduce

  1. Install claude-agent-sdk>=0.1.29 (Python)
  2. Use query() with ClaudeAgentOptions(permission_mode="bypassPermissions")
  3. Run any agent session that uses tools (Read, Glob, Grep, Bash, etc.)
  4. Every tool call produces the Error in hook callback hook_0: Stream closed error

What Should Happen?

In bypassPermissions mode, hook callbacks that attempt stream-based permission requests should either:

  • Not fire at all (permissions are bypassed, no need to request)
  • Be silently caught instead of dumping minified source code + stack traces to stderr

Root Cause

The minified source in the error shows the SubagentStop/Stop hook event handling code (introduced in SDK v0.1.29). The sendRequest function checks this.inputClosed and throws "Stream closed" — the parent process hook tries to communicate over a stream that doesn't exist or is already closed when running in bypass mode.

Workaround

Pin claude-agent-sdk<0.1.29 (v0.1.28 with bundled CLI v2.1.30). This eliminates the errors completely — the new hook events didn't exist yet.

Environment Info

  • Platform: Linux (Ubuntu 24.04 / Zorin OS 18, kernel 6.14.0-37-generic x86_64)
  • Claude Code CLI: 2.1.34
  • claude-agent-sdk (Python): 0.1.29, 0.1.30, 0.1.31 all reproduce
  • Python: 3.12.3
  • Node.js: v24.13.0

Claude Model

Opus (claude-opus-4-6), also reproduces with claude-opus-4-5-20251101

Is this a regression?

Yes, this worked in a previous version

Last Working Version

claude-agent-sdk==0.1.28 (bundled CLI v2.1.30)

View original on GitHub ↗

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