{"record":{"id":"c24db8a5e9f2f7df","repo":"langchain-ai/langchain","slug":"found-run-run-type-run-at-id-run-id-but-expec","errorCode":null,"errorMessage":"Found {run.run_type} run at ID {run_id}, but expected {run_types} run.","messagePattern":"Found (.+?) run at ID (.+?), but expected (.+?) run\\.","errorType":"exception","errorClass":"TracerException","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tracers/core.py","lineNumber":167,"sourceCode":"        self.run_map[str(run.id)] = run\n\n    def _get_run(self, run_id: UUID, run_type: str | set[str] | None = None) -> Run:\n        try:\n            run = self.run_map[str(run_id)]\n        except KeyError as exc:\n            msg = f\"No indexed run ID {run_id}.\"\n            raise TracerException(msg) from exc\n\n        if isinstance(run_type, str):\n            run_types: set[str] | None = {run_type}\n        else:\n            run_types = run_type\n        if run_types is not None and run.run_type not in run_types:\n            msg = (\n                f\"Found {run.run_type} run at ID {run_id}, \"\n                f\"but expected {run_types} run.\"\n            )\n            raise TracerException(msg)\n        return run\n\n    def _create_chat_model_run(\n        self,\n        serialized: dict[str, Any],\n        messages: list[list[BaseMessage]],\n        run_id: UUID,\n        tags: list[str] | None = None,\n        parent_run_id: UUID | None = None,\n        metadata: dict[str, Any] | None = None,\n        name: str | None = None,\n        **kwargs: Any,\n    ) -> Run:\n        \"\"\"Create a chat model run.\"\"\"\n        if self._schema_format not in {\"streaming_events\", \"original+chat\"}:\n            # Please keep this un-implemented for backwards compatibility.\n            # When it's unimplemented old tracers that use the \"original\" format\n            # fallback on the on_llm_start method implementation if they","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tracers/core.py#L149-L185","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nclass MyTracer(BaseTracer):\n    def on_tool_end(self, output, *, run_id, **kw):\n        run = self._get_run(run_id)               # may find a chain run -> mismatch\n\n# after\nclass MyTracer(BaseTracer):\n    def on_tool_end(self, output, *, run_id, **kw):\n        run = self._get_run(run_id, \"tool\")       # correct type expectation\n        # ensure run_id originally came from on_tool_start","handlingStrategy":"try-catch","validationCode":"def run_is_type(tracer, run_id, expected: set[str]) -> bool:\n    run = tracer.run_map.get(str(run_id))\n    return run is not None and run.run_type in expected","typeGuard":null,"tryCatchPattern":"from langchain_core.tracers import TracerException\n\ntry:\n    run = self._get_run(run_id, {\"chain\", \"tool\"})\nexcept TracerException:\n    return  # event of an unexpected kind; skip","preventionTips":["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"],"tags":["langchain","tracing","callbacks","lifecycle"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}