langchain-ai/langchain · error · ValueError

Cannot specify both alternative and alternative_import

Error message

Cannot specify both alternative and alternative_import

What it means

Raised by `_validate_deprecation_params` when a `@deprecated` / `warn_deprecation` call supplies both `alternative` (a free-text replacement description) and `alternative_import` (a dotted import path). The two are mutually exclusive ways to tell users what to use instead; `alternative_import` auto-generates the guidance, so both cannot be given.

Source

Thrown at libs/core/langchain_core/_api/deprecation.py:110

# scope emits a `UserWarning` on Python 3.14+; v1 `FieldInfo` support is handled
# at runtime via `_is_pydantic_v1_field_info`.
T = TypeVar("T", bound=type | Callable[..., Any] | Any)


def _validate_deprecation_params(
    removal: str,
    alternative: str,
    alternative_import: str,
    *,
    pending: bool,
) -> None:
    """Validate the deprecation parameters."""
    if pending and removal:
        msg = "A pending deprecation cannot have a scheduled removal"
        raise ValueError(msg)
    if alternative and alternative_import:
        msg = "Cannot specify both alternative and alternative_import"
        raise ValueError(msg)

    if alternative_import and "." not in alternative_import:
        msg = (
            "alternative_import must be a fully qualified module path. Got "
            f" {alternative_import}"
        )
        raise ValueError(msg)


def deprecated(
    since: str,
    *,
    message: str = "",
    name: str = "",
    alternative: str = "",
    alternative_import: str = "",
    pending: bool = False,
    obj_type: str = "",

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. If the replacement is importable, keep only `alternative_import="pkg.module.attr"` and drop `alternative`.
  2. If the guidance needs prose (e.g. multi-step migration), keep only `alternative=` and drop `alternative_import`.

Example fix

# before
@deprecated("0.3", alternative="Use new_fn", alternative_import="mymod.new_fn")
def old_fn(): ...

# after
@deprecated("0.3", alternative_import="mymod.new_fn")
def old_fn(): ...
Defensive patterns

Strategy: validation

Validate before calling

def validate_alternative(alternative: str, alternative_import: str) -> None:
    if alternative and alternative_import:
        raise ConfigError("pass alternative OR alternative_import, not both")

Prevention

When it happens

Trigger: Any decorator or call like `@deprecated(since="0.3", alternative="Use `x.y.new_api`", alternative_import="x.y.new_api")`. Validation runs at decoration/import time and fails immediately with ValueError.

Common situations: Migrating an existing deprecation that used a prose `alternative` over to the newer `alternative_import` style and leaving the old kwarg in place, or copy-pasting a deprecation block and appending rather than replacing the alternative field.

Related errors


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