Which component is this bug for?
Langchain Instrumentation
馃摐 Description
While using the TraceLoop LangGraph instrumentation (opentelemetry-instrumentation-langchain), successful LangGraph executions are incorrectly reported as ERROR.
The issue occurs when consuming graph.astream() with an async for loop and returning once the desired result is produced. During normal async generator shutdown, Python raises GeneratorExit to close the underlying generator. This is expected control flow and does not indicate an application error.
However, the instrumentation catches GeneratorExit as a BaseException and records it as a span failure. As a result, spans such as invoke_agent and, in our environment, the associated workflow span are marked with StatusCode.ERROR even though the workflow completes successfully.
This leads to misleading traces in observability backends like Langfuse, where successful executions appear as failures and can negatively impact debugging, monitoring, and error-rate metrics.
馃憻 Reproduction steps
- Instrument a LangGraph application using the TraceLoop SDK.
- Execute a graph using graph.astream().
- Consume the stream using an async for loop.
- Return from the loop once the desired output has been produced (instead of consuming the generator to exhaustion).
Example:
async for event in graph.astream(inputs):
if is_final_response(event):
return response
- Inspect the generated trace in Langfuse (or another OpenTelemetry backend).
馃憤 Expected behavior
Successful LangGraph executions should produce successful spans.
Normal async generator shutdown (GeneratorExit) should be treated as expected Python control flow and should not mark spans as ERROR.
馃憥 Actual Behavior with Screenshots
The instrumentation catches GeneratorExit while wrapping graph.astream() and records it as an application failure.
As a result:
- invoke_agent spans are marked as StatusCode.ERROR.
- Workflow spans are also marked as StatusCode.ERROR.
- The application itself completes successfully and returns the expected response.
馃 Python Version
Python 3.12
馃搩 Provide any additional context for the Bug.
The current instrumentation wraps stream()/astream() using except BaseException, which also catches GeneratorExit.
Since GeneratorExit inherits from BaseException (not Exception), normal async generator shutdown is incorrectly treated as an application error.
A possible fix would be to either:
handle GeneratorExit separately and immediately re-raise it without modifying the span, or
catch Exception instead of BaseException, aligning with OpenTelemetry's handling of control-flow exceptions.
In our testing, adding a dedicated GeneratorExit branch before the generic exception handling prevents successful LangGraph executions from being reported as failed while preserving normal error reporting for genuine exceptions.
馃憖 Have you spent some time to check if this bug has been raised before?
Are you willing to submit PR?
Yes I am willing to submit a PR!
Which component is this bug for?
Langchain Instrumentation
馃摐 Description
While using the TraceLoop LangGraph instrumentation (opentelemetry-instrumentation-langchain), successful LangGraph executions are incorrectly reported as ERROR.
The issue occurs when consuming graph.astream() with an async for loop and returning once the desired result is produced. During normal async generator shutdown, Python raises GeneratorExit to close the underlying generator. This is expected control flow and does not indicate an application error.
However, the instrumentation catches GeneratorExit as a BaseException and records it as a span failure. As a result, spans such as invoke_agent and, in our environment, the associated workflow span are marked with
StatusCode.ERROReven though the workflow completes successfully.This leads to misleading traces in observability backends like Langfuse, where successful executions appear as failures and can negatively impact debugging, monitoring, and error-rate metrics.
馃憻 Reproduction steps
Example:
async for event in graph.astream(inputs):
if is_final_response(event):
return response
馃憤 Expected behavior
Successful LangGraph executions should produce successful spans.
Normal async generator shutdown (GeneratorExit) should be treated as expected Python control flow and should not mark spans as ERROR.
馃憥 Actual Behavior with Screenshots
The instrumentation catches GeneratorExit while wrapping graph.astream() and records it as an application failure.
As a result:
馃 Python Version
Python 3.12
馃搩 Provide any additional context for the Bug.
The current instrumentation wraps stream()/astream() using except BaseException, which also catches GeneratorExit.
Since GeneratorExit inherits from BaseException (not Exception), normal async generator shutdown is incorrectly treated as an application error.
A possible fix would be to either:
handle GeneratorExit separately and immediately re-raise it without modifying the span, or
catch Exception instead of BaseException, aligning with OpenTelemetry's handling of control-flow exceptions.
In our testing, adding a dedicated GeneratorExit branch before the generic exception handling prevents successful LangGraph executions from being reported as failed while preserving normal error reporting for genuine exceptions.
馃憖 Have you spent some time to check if this bug has been raised before?
Are you willing to submit PR?
Yes I am willing to submit a PR!