{"record":{"id":"4fcfea3e3e0fd471","repo":"langchain-ai/langchain","slug":"one-or-more-keys-do-not-have-a-corresponding-runna","errorCode":null,"errorMessage":"One or more keys do not have a corresponding runnable","messagePattern":"One or more keys do not have a corresponding runnable","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/router.py","lineNumber":151,"sourceCode":"        return await runnable.ainvoke(actual_input, config)\n\n    @override\n    def batch(\n        self,\n        inputs: list[RouterInput],\n        config: RunnableConfig | list[RunnableConfig] | None = None,\n        *,\n        return_exceptions: bool = False,\n        **kwargs: Any | None,\n    ) -> list[Output]:\n        if not inputs:\n            return []\n\n        keys = [input_[\"key\"] for input_ in inputs]\n        actual_inputs = [input_[\"input\"] for input_ in inputs]\n        if any(key not in self.runnables for key in keys):\n            msg = \"One or more keys do not have a corresponding runnable\"\n            raise ValueError(msg)\n\n        def invoke(\n            runnable: Runnable[Input, Output], input_: Input, config: RunnableConfig\n        ) -> Output | Exception:\n            if return_exceptions:\n                try:\n                    return runnable.invoke(input_, config, **kwargs)\n                except Exception as e:\n                    return e\n            else:\n                return runnable.invoke(input_, config, **kwargs)\n\n        runnables = [self.runnables[key] for key in keys]\n        configs = get_config_list(config, len(inputs))\n        with get_executor_for_config(configs[0]) as executor:\n            return cast(\n                \"list[Output]\",\n                list(executor.map(invoke, runnables, actual_inputs, configs)),","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/router.py#L133-L169","documentation":"`RunnableRouter.batch` pre-validates all inputs before dispatching: if any element of the batch carries a `key` not in the router's runnables, the whole batch is rejected with this ValueError (this check runs before per-item exception handling, so `return_exceptions=True` does not bypass it).","triggerScenarios":"`RouterRunnable({'a': r}).batch([{'key': 'a', ...}, {'key': 'z', ...}])` — one bad key in any batch element fails the entire call, even with `return_exceptions=True`, because the check happens up front.","commonSituations":"Batch-processing user requests where a classifier occasionally emits an unregistered label, killing all N requests; enum keys vs string registry entries; a newly added branch not registered before batching traffic against it.","solutions":["Pre-validate keys before batching: `keys = [i['key'] for i in inputs]; bad = set(keys) - set(router.runnables)` and route bad ones to a fallback.","Register a runnable for every emittable key, including a catch-all.","If you need per-item isolation, batch through a wrapper that catches this ValueError per item instead of relying on `return_exceptions`."],"exampleFix":"// before\nresults = router.batch(inputs)  # dies if ANY key is unregistered\n// after\nvalid = [i for i in inputs if i['key'] in router.runnables]\nfallback = [i for i in inputs if i['key'] not in router.runnables]\nresults = [router.invoke(i) if i in valid else default_run.invoke(i['input']) for i in inputs]","handlingStrategy":"validation","validationCode":"valid_keys = set(router.runnables)\nbad = [i for i in inputs if i['key'] not in valid_keys]\nif bad:\n    inputs = [\n        i if i['key'] in valid_keys else {'key': 'default', 'input': i['input']}\n        for i in inputs\n    ]\nresults = router.batch(inputs)","typeGuard":null,"tryCatchPattern":"try:\n    results = router.batch(inputs)\nexcept ValueError as e:\n    if 'corresponding runnable' in str(e):\n        results = [router.invoke(i) if i['key'] in router.runnables\n                   else default_run.invoke(i['input']) for i in inputs]\n    else:\n        raise","preventionTips":["Pre-validate the key set before batch; return_exceptions does NOT bypass this check.","Map unknown keys to a default branch during preprocessing.","Assert key vocabulary ⊆ router.runnables at app startup."],"tags":["router","batch","pre-validation","lcel"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}