Skip to content

Fail faster when json.loads is doomed#678

Open
lukeyoung100 wants to merge 1 commit intoanthropics:mainfrom
lukeyoung100:patch-2
Open

Fail faster when json.loads is doomed#678
lukeyoung100 wants to merge 1 commit intoanthropics:mainfrom
lukeyoung100:patch-2

Conversation

@lukeyoung100
Copy link

@lukeyoung100 lukeyoung100 commented Mar 13, 2026

Context:
I had an issue in my local setup where I added a hook which outputs a '\a' character with claude's output to trigger a bell when claude is finished answering a question e.g.:
19 "hooks": [
20 {
21 "type": "command",
22 - "command": "printf '\a' >&2; echo -ne '\a' > /dev/tty 2>/dev/null; echo -ne '\a' > /proc/$PPID/fd/1 2>/dev/null"
23 }
24 ]

This triggered a failure scenario where my myclaw daemon was attempting to talk to claude in json format but instead of line 557 running json.loads('{key:value...etc}') it was failing with json.loads('\a{key:value}'). This caused the json.loads to throw an exception, continue in the for loop, and execute a blocking wait on line 28, while it waits more data from claude that will never come. This caused the daemon to hang until a 10 minute timeout was hit.

When I add the exception here it causes the claude sdk to give up way faster. I no longer experienced 10 minute hangs when interacting with the myclaw daemon through gchat. Instead the error message shows up in the logs and I experienced only slightly delayed messages. I'm not 100% why I still got responses, but I suspect that in some retries the '\a' was mssing from claude's output for some reason.

Context:
I had an issue in my local setup where I added a hook which outputs a \a character with claude's output to trigger a bell when claude is finished answering a question e.g.:
      19          "hooks": [
      20            {
      21              "type": "command",
      22 -           "command": "printf '\\a' >&2; echo -ne '\\a' > /dev/tty 2>/dev/null; echo -ne '\\a' > /proc/$PPID/fd/1 2>/dev/null"
      23            }
      24          ]

This triggered a failure scenario where my myclaw daemon was attempting to talk to claude in json format but instead of line 557 running json.loads('{key:value...etc}') it was failing with json.loads('\a{key:value}'). This caused the daemon to hang for 10 minutes.

When I add the exception here it causes the claude sdk to give up way faster. I no longer experienced 10 minute hangs when interacting with the daemon through gchat. Instead the error message shows up in the logs and I experienced only slightly delayed messages.
dotuananh0712 added a commit to dotuananh0712/claude-agent-sdk-python that referenced this pull request Mar 15, 2026
When the buffer contains non-JSON content (e.g., control characters like \a from
shell hooks), json.loads fails and the code continues waiting indefinitely for
valid JSON, causing 10+ minute timeouts.

This fix detects when the buffer contains non-JSON content at the start (after
stripping whitespace) and raises SDKJSONDecodeError immediately instead of
waiting forever.

Fixes anthropics#678
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant