Tracer Version(s)
5.82.0
Node.js Version(s)
22.21.0
Bug Report
ToolInvokePlugin in datadog-plugin-langchain marks a span as errored when the tool throws a LangGraph GraphInterrupt. That exception is not a failure, it is how LangGraph suspends for human-in-the-loop: interrupt() throws, and the graph catches it upstream to persist the checkpoint and pause.
The result is that every client-side/human-in-the-loop tool call appears as an error in APM and LLM Observability, while the application behaves correctly. On a working agent, the trace says the tool failed.
This is the same bug that was reported and fixed on the Python side in DataDog/dd-trace-py#16614 (fixed by PR #16983). There, the integration already exempted ParentCommand from error marking and GraphInterrupt fell through; the fix extended the check.
Reproduce
- Build a LangGraph agent (
createAgent) with a tool whose implementation calls interrupt(...) from @langchain/langgraph.
- Run a turn where the model calls that tool.
- The tool span is marked as an error with
GraphInterrupt, even though the run suspends and resumes normally.
Expected
A GraphInterrupt should close the span without error, as ParentCommand already does.
Suggested fix
@langchain/langgraph exports isGraphBubbleUp, the guard for the base class of GraphInterrupt, ParentCommand and GraphDrained — all of which are graph control flow rather than failures. Guarding on the base class avoids the recurrence that happened in Python, where enumerating the subclasses left one behind.
Note: dd-trace-js has no dedicated langgraph integration (unlike Python), so LangGraph users are traced through the langchain one and hit this by default.
Reproduction Code
No response
Error Logs
No response
Tracer Config
No response
Operating System
No response
Bundling
No Bundling
Tracer Version(s)
5.82.0
Node.js Version(s)
22.21.0
Bug Report
ToolInvokePluginindatadog-plugin-langchainmarks a span as errored when the tool throws a LangGraphGraphInterrupt. That exception is not a failure, it is how LangGraph suspends for human-in-the-loop:interrupt()throws, and the graph catches it upstream to persist the checkpoint and pause.The result is that every client-side/human-in-the-loop tool call appears as an error in APM and LLM Observability, while the application behaves correctly. On a working agent, the trace says the tool failed.
This is the same bug that was reported and fixed on the Python side in DataDog/dd-trace-py#16614 (fixed by PR #16983). There, the integration already exempted
ParentCommandfrom error marking andGraphInterruptfell through; the fix extended the check.Reproduce
createAgent) with a tool whose implementation callsinterrupt(...)from@langchain/langgraph.GraphInterrupt, even though the run suspends and resumes normally.Expected
A
GraphInterruptshould close the span without error, asParentCommandalready does.Suggested fix
@langchain/langgraphexportsisGraphBubbleUp, the guard for the base class ofGraphInterrupt,ParentCommandandGraphDrained— all of which are graph control flow rather than failures. Guarding on the base class avoids the recurrence that happened in Python, where enumerating the subclasses left one behind.Note: dd-trace-js has no dedicated
langgraphintegration (unlike Python), so LangGraph users are traced through thelangchainone and hit this by default.Reproduction Code
No response
Error Logs
No response
Tracer Config
No response
Operating System
No response
Bundling
No Bundling