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 errorsView on GitHub (pinned to 2e5f0e2b42)
Solutions
- Assign model_config instead of merely annotating it: change `model_config: ConfigDict` to `model_config = ConfigDict(...)`.
- If you intended a real field, rename it to something other than model_config (the name is reserved).
- 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
- Always assign model_config with =, never only annotate it.
- After V1->V2 migration, grep for stray `model_config:` annotations.
- Reserve the name model_config exclusively for configuration.
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
- config-both
- Config has no attribute {name!r}
- validate-by-alias-and-name-false
- validator-field-config-info
- validator-v1-signature
AI-assisted analysis of pydantic/pydantic@2e5f0e2b42 (2026-08-04).
Data as JSON: /data/errors/da1c3c043629c4b4.json.
Report an issue: GitHub.