Skip to content

Streaming tool use: unhelpful error message when model emits malformed JSON (non-beta path missing try-except) #1265

@AbdoKnbGit

Description

@AbdoKnbGit

When using client.messages.stream() with tools, if the model emits malformed JSON during an input_json_delta
event, the user gets a raw internal parser error with no context:

ValueError: expected ident at line 1 column 11

The beta path (_beta_messages.py) already wraps the same call with a clear, actionable message. The non-beta path
(_messages.py) is simply missing the same try-except.

Impact

Every user of client.messages.stream() with tool calling is affected. When this triggers, there is no indication
that the error came from tool input JSON parsing, no mention of what JSON was received, and no guidance on what to do.
It looks like an SDK crash.

Confirmed with real API call (anthropic==0.86.0)

I made a real streaming tool call to claude-haiku-4-5, captured the response, then replayed the events
through accumulate_event with a corrupted JSON delta to trigger the error path in both the non-beta and beta
accumulators.

Normal streaming tool call works fine:

STEP 1: Real API streaming tool call (claude-haiku-4-5)

  received: message_start
  received: content_block_start
  received: content_block_delta
  received: input_json
  received: content_block_delta
  received: input_json
  received: content_block_delta
  received: input_json
  received: content_block_stop
  received: message_delta
  received: message_stop

  Tool called: get_weather({'city': 'Paris'})

Corrupted delta ({"city": INVALID_VALUE}) through both paths:

NON-BETA PATH (accumulate_event from _messages.py):
  ValueError: "expected ident at line 1 column 11"
  ^ Raw jiter error -- no context for the user

BETA PATH (accumulate_event from _beta_messages.py):
  ValueError: "Unable to parse tool parameter JSON from model.
  Please retry your request or adjust your prompt.
  Error: expected ident at line 1 column 11.
  JSON: {"city": INVALID_VALUE}"
  ^ Helpful: tells the user what happened and what to do

Reproduction

from anthropic.types import (
    RawMessageStartEvent, RawContentBlockStartEvent, RawContentBlockDeltaEvent,
)
from anthropic.types.message import Message
from anthropic.types.usage import Usage
from anthropic.types.tool_use_block import ToolUseBlock
from anthropic.types.input_json_delta import InputJSONDelta
from anthropic.types.direct_caller import DirectCaller
from anthropic.lib.streaming._messages import accumulate_event

msg = Message(
    id="msg_123", type="message", role="assistant", content=[],
    model="claude-haiku-4-5", stop_reason=None, stop_sequence=None,
    usage=Usage(input_tokens=10, output_tokens=1),
)
snapshot = accumulate_event(
    event=RawMessageStartEvent(type="message_start", message=msg),
    current_snapshot=None,
)
snapshot = accumulate_event(
    event=RawContentBlockStartEvent(
        type="content_block_start", index=0,
        content_block=ToolUseBlock(
            type="tool_use", id="toolu_01", name="get_weather",
            input={}, caller=DirectCaller(type="direct"),
        ),
    ),
    current_snapshot=snapshot,
)

# Malformed JSON delta -- unquoted value
accumulate_event(
    event=RawContentBlockDeltaEvent(
        type="content_block_delta", index=0,
        delta=InputJSONDelta(type="input_json_delta", partial_json='{"city": INVALID_VALUE}'),
    ),
    current_snapshot=snapshot,
)
# Actual:   ValueError("expected ident at line 1 column 11")
# Expected: ValueError("Unable to parse tool parameter JSON from model. ...")

Root cause

src/anthropic/lib/streaming/_messages.py line 480 -- bare from_json() with no error handling:

if json_buf:
    content.input = from_json(json_buf, partial_mode=True)

src/anthropic/lib/streaming/_beta_messages.py lines 500-510 -- same call, already wrapped:

if json_buf:
    try:
        content.input = from_json(json_buf, partial_mode=True)
    except ValueError as e:
        raise ValueError(
            f"Unable to parse tool parameter JSON from model. "
            f"Please retry your request or adjust your prompt. "
            f"Error: {e}. JSON: {json_buf.decode('utf-8')}"
        ) from e

Fix

Wrap the from_json call in _messages.py with the same try-except. 6 lines, zero behavior change for valid JSON.

Environment

  • anthropic version: 0.86.0
  • Python: 3.13
  • OS: Windows 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions