{"record":{"id":"004649adb1f97f87","repo":"langchain-ai/langchain","slug":"if-exception-key-is-specified-then-input-must-be","errorCode":null,"errorMessage":"If 'exception_key' is specified then input must be a dictionary.However found a type of {type(input)} for input","messagePattern":"If 'exception_key' is specified then input must be a dictionary\\.However found a type of (.+?) for input","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/fallbacks.py","lineNumber":173,"sourceCode":"    def runnables(self) -> Iterator[Runnable[Input, Output]]:\n        \"\"\"Iterator over the `Runnable` and its fallbacks.\n\n        Yields:\n            The `Runnable` then its fallbacks.\n        \"\"\"\n        yield self.runnable\n        yield from self.fallbacks\n\n    @override\n    def invoke(\n        self, input: Input, config: RunnableConfig | None = None, **kwargs: Any\n    ) -> Output:\n        if self.exception_key is not None and not isinstance(input, dict):\n            msg = (\n                \"If 'exception_key' is specified then input must be a dictionary.\"\n                f\"However found a type of {type(input)} for input\"\n            )\n            raise ValueError(msg)\n        # setup callbacks\n        config = ensure_config(config)\n        callback_manager = get_callback_manager_for_config(config)\n        # start the root run\n        run_manager = callback_manager.on_chain_start(\n            None,\n            input,\n            name=config.get(\"run_name\") or self.get_name(),\n            run_id=config.pop(\"run_id\", None),\n        )\n        first_error = None\n        last_error = None\n        for runnable in self.runnables:\n            try:\n                if self.exception_key and last_error is not None:\n                    input[self.exception_key] = last_error  # type: ignore[index]\n                child_config = patch_config(config, callbacks=run_manager.get_child())\n                with set_config_context(child_config) as context:","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/fallbacks.py#L155-L191","documentation":"`RunnableWithFallbacks.invoke` requires that when `exception_key` is set (failures are recorded into the input dict under that key), the input must be a `dict`, because the mechanism writes the error back into the input before running fallbacks. A non-dict input fails the `isinstance(input, dict)` check and `ValueError` is raised before any runnable executes.","triggerScenarios":"Creating a fallback with `runnable.with_fallbacks(fallbacks, exception_key=\"errors\")` and then invoking it with a string, list, or object input: `with_fallbacks.invoke(\"hello\")`, or a chain whose preceding step emits a plain string (e.g. a `RunnableLambda` returning text) piped into the fallback-wrapped step.","commonSituations":"Wrapping a parser or model step in fallbacks and feeding it a raw string; converting an existing `.with_fallbacks(...)` chain to record errors via `exception_key` without changing the pipeline so the input stays a dict; passing a Pydantic model object instead of its `.model_dump()`.","solutions":["Remove `exception_key` if you do not need error details recorded in the input.","Feed a dict: wrap the value as `{\"input\": value}` (or a meaningful key) before it reaches the fallback runnable, and update downstream prompts to read that key.","If the input is a Pydantic object, pass `model.model_dump()`."],"exampleFix":"# before\nfb = parser.with_fallbacks([other_parser], exception_key=\"errors\")\nout = fb.invoke(\"some text\")  # ValueError\n\n# after\nout = fb.invoke({\"text\": \"some text\", \"errors\": None})  # and read input[\"text\"] inside","handlingStrategy":"validation","validationCode":"if fb.exception_key is not None:\n    assert isinstance(inputs_payload, dict), \"exception_key requires dict input\"\nfb.invoke(inputs_payload)","typeGuard":"from typing import TypeGuard\n\ndef is_dict_input(x: object) -> TypeGuard[dict]:\n    return isinstance(x, dict)","tryCatchPattern":null,"preventionTips":["Only set exception_key when your pipeline carries dict payloads end-to-end.","Standardize on dict inputs (e.g. {\"text\": ...}) before fallback-wrapped runnables.","Convert Pydantic models with .model_dump() before invoke."],"tags":["fallbacks","value-error","input-validation","langchain-core"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}