langchain-ai/langchain · error · TracerException
Found {run.run_type} run at ID {run_id}, but expected {run_t
Error message
Found {run.run_type} run at ID {run_id}, but expected {run_types} run. What it means
After resolving a run by id, _get_run verifies the run's type (llm/chain/tool/...) matches the expected type for the event being handled. A mismatch — e.g. treating a chain run as a tool run — means start/end events of different kinds shared one run_id, and raises TracerException.
Source
Thrown at libs/core/langchain_core/tracers/core.py:167
self.run_map[str(run.id)] = run
def _get_run(self, run_id: UUID, run_type: str | set[str] | None = None) -> Run:
try:
run = self.run_map[str(run_id)]
except KeyError as exc:
msg = f"No indexed run ID {run_id}."
raise TracerException(msg) from exc
if isinstance(run_type, str):
run_types: set[str] | None = {run_type}
else:
run_types = run_type
if run_types is not None and run.run_type not in run_types:
msg = (
f"Found {run.run_type} run at ID {run_id}, "
f"but expected {run_types} run."
)
raise TracerException(msg)
return run
def _create_chat_model_run(
self,
serialized: dict[str, Any],
messages: list[list[BaseMessage]],
run_id: UUID,
tags: list[str] | None = None,
parent_run_id: UUID | None = None,
metadata: dict[str, Any] | None = None,
name: str | None = None,
**kwargs: Any,
) -> Run:
"""Create a chat model run."""
if self._schema_format not in {"streaming_events", "original+chat"}:
# Please keep this un-implemented for backwards compatibility.
# When it's unimplemented old tracers that use the "original" format
# fallback on the on_llm_start method implementation if theyView on GitHub (pinned to e32fa9a52e)
Solutions
- Use distinct, framework-generated run_ids per run and route end events to the matching on_<type>_end handler
- When subclassing BaseTracer, pass the correct run_type to _get_run (or None to skip the check)
- Don't reuse a run_id across chain/tool/llm boundaries
Example fix
# before
class MyTracer(BaseTracer):
def on_tool_end(self, output, *, run_id, **kw):
run = self._get_run(run_id) # may find a chain run -> mismatch
# after
class MyTracer(BaseTracer):
def on_tool_end(self, output, *, run_id, **kw):
run = self._get_run(run_id, "tool") # correct type expectation
# ensure run_id originally came from on_tool_start Defensive patterns
Strategy: try-catch
Validate before calling
def run_is_type(tracer, run_id, expected: set[str]) -> bool:
run = tracer.run_map.get(str(run_id))
return run is not None and run.run_type in expected Try / catch
from langchain_core.tracers import TracerException
try:
run = self._get_run(run_id, {"chain", "tool"})
except TracerException:
return # event of an unexpected kind; skip Prevention
- Give each run a unique run_id from its on_<type>_start and pair it with the matching end handler
- Pass a set of allowed types to _get_run when handling ambiguous events
- Never reuse run_ids across chain, tool, or llm lifecycles
When it happens
Trigger: on_tool_end(..., run_id=<id of a chain run>); on_llm_end against a run created by on_chain_start; custom agents emitting reused ids across different run types.
Common situations: Custom callback handlers forwarding all end events to on_chain_end regardless of kind; generating run_ids manually with uuid4() collisions across types; adapters that bridge tracers to other telemetry systems.
Related errors
- No indexed run ID {run_id}.
- If env_var is set, handle_class must also be set to a non-No
- Chat model tracing is not supported in for {self._schema_for
- File is not open. Use FileCallbackHandler as a context manag
- The dispatcher API does not accept additional keyword argume
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/c24db8a5e9f2f7df.
Report an issue: GitHub.