langchain-ai/langchain · error · ValueError

Parameters {invalid_model_kwargs} should be specified explic

Error message

Parameters {invalid_model_kwargs} should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.

What it means

Raised by the kwargs-filtering helper when `model_kwargs` contains keys that are already declared, recognized fields of the model (`all_required_field_names`). Recognized parameters must be passed explicitly so they are typed, validated, and traced correctly; smuggling them through `model_kwargs` bypasses that contract and LangChain rejects it.

Source

Thrown at libs/core/langchain_core/utils/utils.py:307

            msg = f"Found {field_name} supplied twice."
            raise ValueError(msg)
        if field_name not in all_required_field_names:
            warnings.warn(
                f"""WARNING! {field_name} is not default parameter.
                {field_name} was transferred to model_kwargs.
                Please confirm that {field_name} is what you intended.""",
                stacklevel=7,
            )
            extra_kwargs[field_name] = values.pop(field_name)

    # DON'T USE! Kept for backwards-compatibility but should never have been public.
    invalid_model_kwargs = all_required_field_names.intersection(extra_kwargs.keys())
    if invalid_model_kwargs:
        msg = (
            f"Parameters {invalid_model_kwargs} should be specified explicitly. "
            f"Instead they were passed in as part of `model_kwargs` parameter."
        )
        raise ValueError(msg)

    # DON'T USE! Kept for backwards-compatibility but should never have been public.
    return extra_kwargs


def convert_to_secret_str(value: SecretStr | str) -> SecretStr:
    """Convert a string to a `SecretStr` if needed.

    Args:
        value: The value to convert.

    Returns:
        The `SecretStr` value.
    """
    if isinstance(value, SecretStr):
        return value
    return SecretStr(value)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Move every key named in the error message out of `model_kwargs` into an explicit constructor argument.
  2. If a key is genuinely provider-specific and not a declared field, keep only those keys in `model_kwargs`.
  3. Programmatically split a raw dict: `known = {k: v for k, v in raw.items() if k in declared_fields}; extra = {k: v for k, v in raw.items() if k not in declared_fields}` and pass each to the right place.

Example fix

# before
llm = ChatOpenAI(model_kwargs={"model": "gpt-4o", "logprobs": True})

# after
llm = ChatOpenAI(model="gpt-4o", model_kwargs={"logprobs": True})
Defensive patterns

Strategy: validation

Validate before calling

from pydantic import BaseModel

def split_for_constructor(cls: type[BaseModel], raw: dict) -> tuple[dict, dict]:
    """Split a raw dict into (explicit kwargs, model_kwargs) without overlap."""
    fields = set(cls.model_fields)
    explicit = {k: v for k, v in raw.items() if k in fields}
    extras = {k: v for k, v in raw.items() if k not in fields}
    return explicit, extras

Prevention

When it happens

Trigger: Passing known model parameters inside `model_kwargs`, e.g. `ChatOpenAI(model_kwargs={'model': 'gpt-4o', 'api_key': ...})` where `model` and `api_key` are declared fields of the class. Any intersection between `model_kwargs` keys and the model's declared field names triggers it.

Common situations: Treating `model_kwargs` as a generic catch-all for the whole provider request; migrating code from raw OpenAI SDK calls where everything went into one dict; a field being promoted from unknown to declared after an upgrade, so previously-tolerated `model_kwargs` entries now intersect with field names.

Related errors


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