Version: opentelemetry-util-genai 1.1b0 (_invocation.py:199).
What happens. _start attaches the invocation span to the current context and stores the
token; _finish calls detach(context_token) inside a bare try/except Exception: pass, but the
call it wraps is opentelemetry.context.detach, which itself catches the underlying ValueError
and logs Failed to detach context with a traceback at ERROR level. When the invocation is
started and stopped in different contextvars contexts — every async LangGraph run, where the
on_chain_start and on_chain_end callbacks execute in different tasks — one traceback is
logged per graph invocation, and the ended workflow span remains the current span in the calling
task.
Reproduce. A LangGraph StateGraph with one node, invoked with await graph.ainvoke(...)
under the official LangChain instrumentation with a TelemetryHandler; watch the
opentelemetry.context logger.
Suggested fix. Detach only when the token was created in the current context (compare
contextvars.copy_context() identity or catch ValueError before the API logs it), or give the
invocation an explicit "end without detach" path for callers that cannot guarantee the same
context. Consider making the log level DEBUG for this specific mismatch, since the span itself is
unaffected.
Downstream workaround (forgehawk SDK). A counting logging.Filter on the opentelemetry.context logger,
installed by forgehawk.init() and reported once through the SDK's own log and
forgehawk.status()["suppressed_detach_errors"] (sdk/python/src/forgehawk/_otel_noise.py).
Found while building the forgehawk Python SDK (ZioSec) on top of opentelemetry-util-genai; happy to open a PR for the suggested fix if maintainers agree with the direction.
Version:
opentelemetry-util-genai1.1b0 (_invocation.py:199).What happens.
_startattaches the invocation span to the current context and stores thetoken;
_finishcallsdetach(context_token)inside a baretry/except Exception: pass, but thecall it wraps is
opentelemetry.context.detach, which itself catches the underlyingValueErrorand logs
Failed to detach contextwith a traceback at ERROR level. When the invocation isstarted and stopped in different
contextvarscontexts — every async LangGraph run, where theon_chain_startandon_chain_endcallbacks execute in different tasks — one traceback islogged per graph invocation, and the ended workflow span remains the current span in the calling
task.
Reproduce. A LangGraph
StateGraphwith one node, invoked withawait graph.ainvoke(...)under the official LangChain instrumentation with a
TelemetryHandler; watch theopentelemetry.contextlogger.Suggested fix. Detach only when the token was created in the current context (compare
contextvars.copy_context()identity or catchValueErrorbefore the API logs it), or give theinvocation an explicit "end without detach" path for callers that cannot guarantee the same
context. Consider making the log level DEBUG for this specific mismatch, since the span itself is
unaffected.
Downstream workaround (forgehawk SDK). A counting
logging.Filteron theopentelemetry.contextlogger,installed by
forgehawk.init()and reported once through the SDK's own log andforgehawk.status()["suppressed_detach_errors"](sdk/python/src/forgehawk/_otel_noise.py).Found while building the forgehawk Python SDK (ZioSec) on top of opentelemetry-util-genai; happy to open a PR for the suggested fix if maintainers agree with the direction.