langchain-ai/langchain · error · ValueError
RunnableSequence contains conflicting config specsfor {spec_
Error message
RunnableSequence contains conflicting config specsfor {spec_id}: {[first, *others]} What it means
When collecting `configurable_fields` specs for a `RunnableSequence`, langchain groups specs by `id` and requires all specs sharing an id to be equal. If two steps in the sequence declare a configurable field with the same id but different definitions (different options/annotations), this ValueError is raised. Note the message itself is missing a space ('specsfor') — a cosmetic bug in the f-string.
Source
Thrown at libs/core/langchain_core/runnables/utils.py:708
Raises:
ValueError: If the runnable sequence contains conflicting config specs.
"""
grouped = groupby(
sorted(specs, key=lambda s: (s.id, *(s.dependencies or []))), lambda s: s.id
)
unique: list[ConfigurableFieldSpec] = []
for spec_id, dupes in grouped:
first = next(dupes)
others = list(dupes)
if len(others) == 0 or all(o == first for o in others):
unique.append(first)
else:
msg = (
"RunnableSequence contains conflicting config specs"
f"for {spec_id}: {[first, *others]}"
)
raise ValueError(msg)
return unique
class _RootEventFilter:
def __init__(
self,
*,
include_names: Sequence[str] | None = None,
include_types: Sequence[str] | None = None,
include_tags: Sequence[str] | None = None,
exclude_names: Sequence[str] | None = None,
exclude_types: Sequence[str] | None = None,
exclude_tags: Sequence[str] | None = None,
) -> None:
"""Utility to filter the root event in the astream_events implementation.
This is simply binding the arguments to the namespace to make save on
a bit of typing in the astream_events implementation.View on GitHub (pinned to e32fa9a52e)
Solutions
- Give each field a globally unique id per definition (e.g. 'chat_model' vs 'fallback_model') so no id conflict occurs.
- If both steps must share one id, make the `ConfigurableFieldSpec` definitions identical (same options, annotation, default, name).
- Inspect `chain.config_schema()` / `chain.configurable_fields()` to see the colliding specs before wiring `.with_config`.
Example fix
# before
llm_a = chat_a.with_configurable_fields(model=ConfigurableField(id='model', options={'gpt': ..., 'gpt4': ...}))
llm_b = chat_b.with_configurable_fields(model=ConfigurableField(id='model', options={'haiku': ..., 'sonnet': ...}))
seq = llm_a | llm_b # conflicting spec id 'model'
# after
llm_b = chat_b.with_configurable_fields(model=ConfigurableField(id='fallback_model', options={'haiku': ..., 'sonnet': ...}))
seq = llm_a | llm_b Defensive patterns
Strategy: validation
Validate before calling
from collections import defaultdict
def spec_ids_unique(seq_steps) -> bool:
seen = defaultdict(list)
for step in seq_steps:
for spec in getattr(step, 'config_specs', lambda: [])():
seen[spec.id].append(spec)
for sid, specs in seen.items():
if len({repr(s) for s in specs}) > 1:
return False # same id, differing definitions -> will raise
return True
assert spec_ids_unique(seq.steps) Try / catch
try:
final = seq.with_config(configurable={'model': 'gpt'})
except ValueError as e:
if 'conflicting config specs' in str(e):
# rename the colliding field id on one step and rebuild
rebuild_with_unique_ids()
else:
raise Prevention
- Use a unique ConfigurableField id per definition across the whole sequence.
- Identical ids must have byte-identical spec definitions.
- Inspect chain.configurable_fields() when composing configurable chains.
When it happens
Trigger: Composing a sequence where two runnables each call `ConfigurableField(id='model', ...)` with different `options`, `name`, or `default` values — e.g. building `prompt | llm.with_configurable_fields(model=...) | llm2.with_configurable_fields(model=...)` with mismatched field definitions.
Common situations: Reusing a configurable-field id across two partner models (e.g. an OpenAI and an Anthropic chat both configurable as `model`) inside one sequence; copy-pasting `with_configurable_fields` blocks and editing only one; building `.with_config(configurable={...})` chains after a refactor changed one field's options.
Related errors
- Structured prompts need to be piped to a language model.
- Runnable {self.get_name()} doesn't have an inferable InputTy
- Runnable {self.get_name()} doesn't have an inferable OutputT
- Configuration key {key} not found in {self}: available keys
- RunnableSequence must have at least {_RUNNABLE_SEQUENCE_MIN_
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/082bb719ae1739ae.
Report an issue: GitHub.