AgentFixboard

interrupt() inside a tool is reported as a tool-error on the tools stream

A tool that calls interrupt() emits a tools stream event {'event': 'tool-error', 'tool_call_id': 'tc1', 'message': "(Interrupt(value='ok?', id='...'),)"} instead of pausing only on __interrupt__. The structured Interrupt id and value are flattened to str(error).

From GitHub

langchain-ai/langgraph

Difficulty
Easy
Time
~5 min
Steps
2
Fixed in
—
Last checked

Not fixed upstream yet: the issue is open. Source: issue open. Last checked 2026-10-20.

Symptom

A tool that calls interrupt() emits a tools stream event {'event': 'tool-error', 'tool_call_id': 'tc1', 'message': "(Interrupt(value='ok?', id='...'),)"} instead of pausing only on __interrupt__. The structured Interrupt id and value are flattened to str(error).

Evidence what you'll see

  • The report's print for stream_mode=["tools"] is {'event': 'tool-started', ...} then that tool-error payload. The expected tools stream is only tool-started.
  • The handler is StreamToolCallHandler._error in libs/langgraph/langgraph/pregel/_tools.py, which sends "event": "tool-error" and "message": str(error) for every exception.
  • Reproduced on main and on langgraph 1.2.6, Python 3.12.

Why it happens

GraphInterrupt is a GraphBubbleUp control-flow pause, not a tool failure. _runner, _executor, and _retry already skip GraphBubbleUp. The tools stream handler does not, so a pause is labeled tool-error and the Interrupt objects are lost.

Affected versions

langgraph 1.2.6 and main, Python 3.12. The linked issue does not name an operating system.

Fix steps

0 of 2 done

Your check marks stay in this browser only.

How to check it worked

  • A tool that return interrupt(question) emits tool-started on the tools stream and no tool-error, and graph.get_state(config).interrupts still has the Interrupt id and value.

If it still fails

  • Pull requests 8219 and 8282 skip tool-error when isinstance(error, GraphBubbleUp) and were closed without merge.
  • The linked issue does not name a release that keeps the Interrupt payload on the tools stream.

Sources and credit

Summarized in our own words from these public reports. Credit goes to their authors.

Provided as is, without warranty. Try changes in a non-production environment and back up first. Security-related steps: verify against the official docs. Terms · Request removal or attribution change

Hit an error we don't cover? Submit it