langchain-ai/langchain · error · ValueError

Unknown alternative: {which}

Error message

Unknown alternative: {which}

What it means

`RunnableConfigurableAlternatives._configure` resolves the requested alternative key from `config["configurable"]`. If the key equals neither `default_key` (typically `'default'`) nor any key in `self.alternatives`, it raises `ValueError: Unknown alternative`. This is the runtime enforcement that only registered alternatives may be selected.

Source

Thrown at libs/core/langchain_core/runnables/configurable.py:637

                "RunnableConfig",
                {
                    **config,
                    "configurable": {
                        k.removeprefix(f"{self.which.id}=={which}/"): v
                        for k, v in config.get("configurable", {}).items()
                    },
                },
            )
        # return the chosen alternative
        if which == self.default_key:
            return (self.default, config)
        if which in self.alternatives:
            alt = self.alternatives[which]
            if isinstance(alt, Runnable):
                return (alt, config)
            return (alt(), config)
        msg = f"Unknown alternative: {which}"
        raise ValueError(msg)


def prefix_config_spec(
    spec: ConfigurableFieldSpec, prefix: str
) -> ConfigurableFieldSpec:
    """Prefix the id of a `ConfigurableFieldSpec`.

    This is useful when a `RunnableConfigurableAlternatives` is used as a
    `ConfigurableField` of another `RunnableConfigurableAlternatives`.

    Args:
        spec: The `ConfigurableFieldSpec` to prefix.
        prefix: The prefix to add.

    Returns:
        The prefixed `ConfigurableFieldSpec`.
    """
    return (

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Print the accepted keys first: `runnable.config_schema()` (or inspect `.config_specs()`) to see valid alternative ids.
  2. Correct the key in `with_config(configurable={...})` to exactly match a registered option id (keys are case- and punctuation-sensitive).
  3. If the alternative should exist, register it in `with_configurable_alternatives(...)` / `ConfigurableField` options where the field was declared.
  4. If configs come from user input or a file, validate the key against the schema before invoking the runnable.

Example fix

# before
llm.with_config(configurable={"model": "gpt4-turbo"}).invoke(...)  # unregistered key

# after
# option registered as "gpt-4-turbo"
llm.with_config(configurable={"model": "gpt-4-turbo"}).invoke(...)
Defensive patterns

Strategy: validation

Validate before calling

valid_keys = {s["id"] for spec in runnable.config_specs() for s in spec.get("alternatives", [])}
if key not in valid_keys:
    raise ValueError(f"unknown alternative {key!r}; valid: {sorted(valid_keys)}")
runnable.with_config(configurable={field: key}).invoke(...)

Try / catch

try:
    out = runnable.with_config(configurable={field: key}).invoke(x)
except ValueError as e:
    if "Unknown alternative" in str(e):
        # fall back to the declared default alternative
        out = runnable.invoke(x)
    else:
        raise

Prevention

When it happens

Trigger: Calling `.with_config(configurable={<field>: 'mistyped_key'})` or `.bind(...)`/invoke-time config on a field created with `ConfigurableField(id=..., options=[...])` / `with_configurable_alternatives(...)`, where the selected key has a typo, wrong casing, or was never registered as an option.

Common situations: Selecting `configurable={"llm": "gpt4-turbo"}` when the option is registered as `'gpt-4-turbo'`; moving configuration between environments where an alternative exists in one deployment's factory but not another; renaming an option id in code but not in persisted configs, prompts, or environment-driven settings; passing the option's value instead of its key.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/65885b078f17db59. Report an issue: GitHub.