Environment
sentry-sdk 2.59.0 (also confirmed present on master / 2.60.0)
langchain-core 1.x, langgraph 0.x
- LangChain integration auto-enabled (not explicitly added)
Problem
When langgraph.types.interrupt() is called from inside a LangChain StructuredTool — the standard pattern for exposing human-in-the-loop pauses as agent tools (e.g. deepagents) — it raises GraphInterrupt, a subclass of langgraph.errors.GraphBubbleUp. This is normal control flow, not an error: LangGraph's pregel executor catches it upstream and checkpoints the graph.
However:
langchain_core's BaseTool.arun does not special-case GraphBubbleUp. It catches it in the generic except (Exception, KeyboardInterrupt) and calls run_manager.on_tool_error(error) before re-raising.
- Sentry's
SentryLangchainCallback.on_tool_error -> _handle_error calls sentry_sdk.capture_exception(error, ...) with no exception-type filtering:
def _handle_error(self, run_id, error):
with capture_internal_exceptions():
if not run_id or run_id not in self.span_map:
return
span_data = self.span_map[run_id]
span = span_data.span
sentry_sdk.capture_exception(error, span.scope) # captures GraphInterrupt as an error
...
Result: every trace-sampled HITL interrupt becomes a false-positive error issue in Sentry. (Note the dedicated LanggraphIntegration is tracing-only and does not have this problem — only the LangChain integration does.)
Expected
GraphBubbleUp exceptions (GraphInterrupt, etc.) are LangGraph control-flow signals and should not be captured as errors. _handle_error (or on_tool_error) should skip them:
try:
from langgraph.errors import GraphBubbleUp
except ImportError:
GraphBubbleUp = ()
def _handle_error(self, run_id, error):
if isinstance(error, GraphBubbleUp):
return # langgraph control flow, not an error
...
Workaround
Consumers can pass ignore_errors=[GraphBubbleUp] to sentry_sdk.init(), but the integration shipping a correct default would be preferable.
Environment
sentry-sdk2.59.0 (also confirmed present onmaster/ 2.60.0)langchain-core1.x,langgraph0.xProblem
When
langgraph.types.interrupt()is called from inside a LangChainStructuredTool— the standard pattern for exposing human-in-the-loop pauses as agent tools (e.g.deepagents) — it raisesGraphInterrupt, a subclass oflanggraph.errors.GraphBubbleUp. This is normal control flow, not an error: LangGraph's pregel executor catches it upstream and checkpoints the graph.However:
langchain_core'sBaseTool.arundoes not special-caseGraphBubbleUp. It catches it in the genericexcept (Exception, KeyboardInterrupt)and callsrun_manager.on_tool_error(error)before re-raising.SentryLangchainCallback.on_tool_error->_handle_errorcallssentry_sdk.capture_exception(error, ...)with no exception-type filtering:Result: every trace-sampled HITL interrupt becomes a false-positive error issue in Sentry. (Note the dedicated
LanggraphIntegrationis tracing-only and does not have this problem — only the LangChain integration does.)Expected
GraphBubbleUpexceptions (GraphInterrupt, etc.) are LangGraph control-flow signals and should not be captured as errors._handle_error(oron_tool_error) should skip them:Workaround
Consumers can pass
ignore_errors=[GraphBubbleUp]tosentry_sdk.init(), but the integration shipping a correct default would be preferable.