langchain-ai/langchain · error · ValueError
One or more keys do not have a corresponding runnable
Error message
One or more keys do not have a corresponding runnable
What it means
`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).
Source
Thrown at libs/core/langchain_core/runnables/router.py:151
return await runnable.ainvoke(actual_input, config)
@override
def batch(
self,
inputs: list[RouterInput],
config: RunnableConfig | list[RunnableConfig] | None = None,
*,
return_exceptions: bool = False,
**kwargs: Any | None,
) -> list[Output]:
if not inputs:
return []
keys = [input_["key"] for input_ in inputs]
actual_inputs = [input_["input"] for input_ in inputs]
if any(key not in self.runnables for key in keys):
msg = "One or more keys do not have a corresponding runnable"
raise ValueError(msg)
def invoke(
runnable: Runnable[Input, Output], input_: Input, config: RunnableConfig
) -> Output | Exception:
if return_exceptions:
try:
return runnable.invoke(input_, config, **kwargs)
except Exception as e:
return e
else:
return runnable.invoke(input_, config, **kwargs)
runnables = [self.runnables[key] for key in keys]
configs = get_config_list(config, len(inputs))
with get_executor_for_config(configs[0]) as executor:
return cast(
"list[Output]",
list(executor.map(invoke, runnables, actual_inputs, configs)),View on GitHub (pinned to e32fa9a52e)
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`.
Example fix
// before results = router.batch(inputs) # dies if ANY key is unregistered // after valid = [i for i in inputs if i['key'] in router.runnables] fallback = [i for i in inputs if i['key'] not in router.runnables] results = [router.invoke(i) if i in valid else default_run.invoke(i['input']) for i in inputs]
Defensive patterns
Strategy: validation
Validate before calling
valid_keys = set(router.runnables)
bad = [i for i in inputs if i['key'] not in valid_keys]
if bad:
inputs = [
i if i['key'] in valid_keys else {'key': 'default', 'input': i['input']}
for i in inputs
]
results = router.batch(inputs) Try / catch
try:
results = router.batch(inputs)
except ValueError as e:
if 'corresponding runnable' in str(e):
results = [router.invoke(i) if i['key'] in router.runnables
else default_run.invoke(i['input']) for i in inputs]
else:
raise Prevention
- 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.
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- No runnable associated with key '{key}'
- Argument 'prompts' is expected to be of type list[str], rece
- callbacks must be the same length as prompts
- tags must be a list of the same length as prompts
- metadata must be a list of the same length as prompts
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/4fcfea3e3e0fd471.
Report an issue: GitHub.