-
Notifications
You must be signed in to change notification settings - Fork 237
Description
Bug
LangGraph uses exceptions inheriting from GraphBubbleUp for control flow — not actual errors:
GraphBubbleUp (base)
├── GraphInterrupt — raised by interrupt() for human-in-the-loop
│ └── NodeInterrupt — deprecated, same purpose
└── ParentCommand — raised by Command() for agent handoffs
The Langchain callback handler already defines CONTROL_FLOW_EXCEPTION_TYPES (line 84) and populates it with GraphBubbleUp (line 89) to filter these out. on_chain_error uses this check correctly (line 583), but three other error handlers do not:
| Handler | Line | Has check? |
|---|---|---|
on_chain_error |
572 | Yes |
on_tool_error |
796 | No |
on_retriever_error |
245 | No |
on_llm_error |
990 | No |
The most impactful is on_tool_error, since LangGraph tools are the primary place where interrupt() and Command() are called.
Impact
Any LangGraph tool that uses interrupt() (human-in-the-loop) or returns a Command() (agent handoff) is incorrectly marked as a red ERROR in Langfuse traces. This pollutes dashboards and makes it impossible to distinguish real tool failures from normal control flow.
Expected behavior
Control-flow exceptions should be recorded with level="DEFAULT" and preserve the status message so users can see why the run stopped, without being flagged as an error.
Suggested fix
Apply the same CONTROL_FLOW_EXCEPTION_TYPES guard to all three handlers, using level="DEFAULT" (instead of None as on_chain_error currently does) to preserve visibility:
if any(isinstance(error, t) for t in CONTROL_FLOW_EXCEPTION_TYPES):
level = "DEFAULT"
else:
level = "ERROR"
observation.update(
level=cast(Optional[Literal["DEBUG", "DEFAULT", "WARNING", "ERROR"]], level),
status_message=str(error),
...
)The same improvement should also be applied to on_chain_error for consistency — its current level=None / status_message=None behavior makes control-flow interruptions invisible in traces.
Related issues
- LangGraph interrupt integration issues: tools marked as ERROR and traces not merged across resume langfuse#10962 — LangGraph
interrupt()tools marked as ERROR - bug: Langfuse trace show error on langgraph ToolNode with Command handoff langfuse#5035 — Command handoff tools incorrectly show error in traces