pydantic/pydantic · error · PydanticUserError

model-config-invalid-field-name

model-config-invalid-field-name

Error message

`model_config` cannot be used as a model field name. Use `model_config` for model configuration.

What it means

In ConfigWrapper.for_model, Pydantic inspects the class namespace annotations. The name model_config is reserved for holding the ConfigDict that configures the model. If model_config appears only as a type annotation (raw_annotations.get('model_config') is truthy) but no actual model_config value is assigned in the namespace, Pydantic treats it as an attempt to declare a model field literally named model_config, which collides with the reserved configuration slot and is rejected with code model-config-invalid-field-name.

Source

Thrown at pydantic/_internal/_config.py:166

            bases: A tuple of base classes.
            namespace: The namespace of the class being created.
            raw_annotations: The (non-evaluated) annotations of the model.
            kwargs: The kwargs passed to the class being created.

        Returns:
            A `ConfigWrapper` instance for `BaseModel`.
        """
        config_new = ConfigDict()
        for base in bases:
            config = getattr(base, 'model_config', None)
            if config:
                config_new.update(config.copy())

        config_class_from_namespace = namespace.get('Config')
        config_dict_from_namespace = namespace.get('model_config')

        if raw_annotations.get('model_config') and config_dict_from_namespace is None:
            raise PydanticUserError(
                '`model_config` cannot be used as a model field name. Use `model_config` for model configuration.',
                code='model-config-invalid-field-name',
            )

        if config_class_from_namespace and config_dict_from_namespace:
            raise PydanticUserError('"Config" and "model_config" cannot be used together', code='config-both')

        config_from_namespace = config_dict_from_namespace or prepare_config(config_class_from_namespace)

        config_new.update(config_from_namespace)

        for k in list(kwargs.keys()):
            if k in config_keys:
                config_new[k] = kwargs.pop(k)

        return cls(config_new)

    # we don't show `__getattr__` to type checkers so missing attributes cause errors

View on GitHub (pinned to 2e5f0e2b42)

Solutions

  1. Assign model_config instead of merely annotating it: change `model_config: ConfigDict` to `model_config = ConfigDict(...)`.
  2. If you intended a real field, rename it to something other than model_config (the name is reserved).
  3. Remove the stray annotation if it was left over from a V1->V2 migration.

Example fix

# before
class M(BaseModel):
    model_config: ConfigDict  # annotation only -> error

# after
class M(BaseModel):
    model_config = ConfigDict(extra='forbid')
Defensive patterns

Strategy: validation

Validate before calling

from typing import get_type_hints
import inspect

def ensure_model_config_assigned(cls):
    anns = getattr(cls, '__annotations__', {})
    if 'model_config' in anns and 'model_config' not in cls.__dict__:
        raise TypeError('model_config is annotated but not assigned; use model_config = ConfigDict(...)')

Type guard

def is_valid_model_config(namespace: dict) -> bool:
    return not (namespace.get('__annotations__', {}).get('model_config')
                and namespace.get('model_config') is None)

Try / catch

try:
    class M(BaseModel): ...
except PydanticUserError as e:
    if e.code == 'model-config-invalid-field-name':
        # assign model_config = ConfigDict(...) instead of annotating
        raise
    raise

Prevention

When it happens

Trigger: Writing `class M(BaseModel): model_config: ConfigDict` (annotation only, no assignment), or `class M(BaseModel): model_config: str` treating it as a field, or annotating model_config without assigning a ConfigDict while intending a field. The check at _config.py:165-169 fires when raw_annotations has 'model_config' but namespace.get('model_config') is None.

Common situations: Migrating from V1 where developers wrote a Config inner class and accidentally leave a stray `model_config: ...` annotation; forgetting to assign the ConfigDict after annotating it (e.g., `model_config: ConfigDict` then never doing `model_config = ConfigDict(...)`).

Related errors


AI-assisted analysis of pydantic/pydantic@2e5f0e2b42 (2026-08-04). Data as JSON: /data/errors/da1c3c043629c4b4.json. Report an issue: GitHub.