CallbackHandler.on_chain_start does not pass trace_name to propagate_attributes, causing non-deterministic trace names on LangGraph resume
@hassiebp がすでに取り組んでいます。
2026年4月4日 から。
評価
この issue はまだ評価されていません。
説明
Bug Description
When using CallbackHandler with LangGraph, trace names are non-deterministic on graph resume (e.g., after a human-in-the-loop interrupt). Sometimes the trace gets the correct compiled graph name (e.g., "my-agent"), sometimes it gets an empty string "".
Root Cause
In CallbackHandler.on_chain_start (line 320-325), when the root chain starts (parent_run_id is None), propagate_attributes() is called without the trace_name parameter:
# Current code (simplified):
span_name = self.get_langchain_run_name(serialized, **kwargs) # line 310
if parent_run_id is None:
self._propagation_context_manager = propagate_attributes(
user_id=...,
session_id=...,
tags=...,
metadata=...,
# trace_name is NOT passed here
)
The propagate_attributes() API does support a trace_name parameter, but it's not being used.
Why This Causes Non-Deterministic Trace Names
LangGraph's Pregel.stream() calls on_chain_start with:
# langgraph/pregel/main.py
name=config.get("run_name", self.get_name()) # self.get_name() = compiled graph name
On initial run, the first on_chain_start event comes from the root graph, so span_name correctly reflects the compiled graph name (e.g., "my-agent").
On resume (e.g., after HITL interrupt via Command(resume=...)), the graph may resume from an internal node. The first on_chain_start event can come from a subgraph node whose name is "", causing the trace to get an empty name.
Since trace_name is not propagated via propagate_attributes(), the trace name depends entirely on whichever on_chain_start fires first — which is non-deterministic on resume.
Reproduction
from langgraph.graph import StateGraph
from langgraph.types import Command, interrupt
from langfuse.langchain import CallbackHandler
# Build a graph with HITL interrupt
def my_node(state):
answer = interrupt("question?")
return {"messages": [AIMessage(content=answer)]}
graph = builder.compile(checkpointer=checkpointer, name="my-agent")
handler = CallbackHandler()
# Initial run — trace name = "my-agent" ✅
for chunk in graph.stream(input, config={"callbacks": [handler]}):
pass
# Resume — trace name is "" (non-deterministic) ❌
for chunk in graph.stream(Command(resume="yes"), config={"callbacks": [handler]}):
pass
Proposed Fix
Pass span_name as trace_name to propagate_attributes():
if parent_run_id is None:
self._propagation_context_manager = propagate_attributes(
trace_name=span_name, # <-- add this
user_id=parsed_trace_attributes.get("user_id", None),
session_id=parsed_trace_attributes.get("session_id", None),
tags=parsed_trace_attributes.get("tags", None),
metadata=parsed_trace_attributes.get("metadata", None),
)
This ensures the trace name is always set from the callback's name parameter, regardless of which internal node fires first on resume.
Workaround
Setting run_name in the LangGraph config forces a consistent name:
config = {"run_name": "my-agent", "callbacks": [handler]}
graph.stream(Command(resume="yes"), config=config)
This works because LangGraph uses config.get("run_name", self.get_name()), so an explicit run_name overrides the non-deterministic behavior. However, users shouldn't need to duplicate the compiled graph name into the config.
Environment
- langfuse SDK: 4.x (OTel-based)
- langgraph: 0.4.x
- Python: 3.12+
Related
propagate_attributes()already supportstrace_name— it's just not used in the callback handler_parse_langfuse_trace_attributes()parseslangfuse_session_id,langfuse_user_id,langfuse_tagsfrom metadata, but has no support forlangfuse_trace_nameeither
- 主要言語
- Python
- スター
- 468
- フォーク
- 349
- 平均マージ
- 12時間 16分
- マージ済み PR(30日)
- 27
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
langfuse/langfuse-python のほかの issue
-
feat-scores sdk-python unconfirmed-bug
langfuse/langfuse-python#1890 · 担当者 1 名 ·
-
bug feat-evals sdk-python
langfuse/langfuse-python#1861 · コメント 1 件 · 担当者 1 名 ·
-
improvement sdk-python
langfuse/langfuse-python#1856 · 担当者 1 名 ·
-
improvement sdk-python security
langfuse/langfuse-python#1855 · 担当者 1 名 ·
-
billing bug feat-billing feat-llm-cost-tracking integration-openai sdk-python
langfuse/langfuse-python#1834 · コメント 1 件 · 担当者 1 名 ·
langfuse/langfuse-python の issue をすべて見る
似ている issue
-
sponsored
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
Diaoul/subliminal#1382 ·
-
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
-
triage/confirmed
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
agentscope-ai/agentscope#2775 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100