Skip to content

馃悰 Bug Report: LangGraph instrumentation incorrectly marks successful astream() executions as ERROR due to GeneratorExit#4385

Description

@karthik2oo4-git

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

  1. Instrument a LangGraph application using the TraceLoop SDK.
  2. Execute a graph using graph.astream().
  3. Consume the stream using an async for loop.
  4. 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
  5. 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:

  1. invoke_agent spans are marked as StatusCode.ERROR.
  2. Workflow spans are also marked as StatusCode.ERROR.
  3. 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?

  • I checked and didn't find similar issue

Are you willing to submit PR?

Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions