pydantic/pydantic · error · TypeError

Invalid `validation_alias` type. it should be `str`, `AliasC

Error message

Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`

What it means

Raised by Field() at fields.py:1347 when validation_alias is supplied but is not an instance of str, AliasChoices, or AliasPath. Pydantic restricts validation aliases to these three types so the alias resolution algorithm can deterministically traverse the input payload.

Source

Thrown at pydantic/fields.py:1347

        raise PydanticUserError('`regex` is removed. use `pattern` instead', code='removed-kwargs')

    if extra:
        warn(
            'Using extra keyword arguments on `Field` is deprecated and will be removed.'
            ' Use `json_schema_extra` instead.'
            f' (Extra keys: {", ".join(k.__repr__() for k in extra.keys())})',
            PydanticDeprecatedSince20,
            stacklevel=2,
        )
        if not json_schema_extra or json_schema_extra is _Unset:
            json_schema_extra = extra  # type: ignore

    if (
        validation_alias
        and validation_alias is not _Unset
        and not isinstance(validation_alias, (str, AliasChoices, AliasPath))
    ):
        raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`')

    if serialization_alias in (_Unset, None) and isinstance(alias, str):
        serialization_alias = alias

    if validation_alias in (_Unset, None):
        validation_alias = alias

    include = extra.pop('include', None)  # type: ignore
    if include is not None:
        warn(
            '`include` is deprecated and does nothing. It will be removed, use `exclude` instead',
            PydanticDeprecatedSince20,
            stacklevel=2,
        )

    return FieldInfo.from_field(
        default,
        default_factory=default_factory,

View on GitHub (pinned to 2e5f0e2b42)

Solutions

  1. Use a plain str for a single-key alias: Field(validation_alias='alt_name').
  2. Wrap a nested path with AliasPath: Field(validation_alias=AliasPath('user', 'email')).
  3. Wrap multiple alternative keys with AliasChoices: Field(validation_alias=AliasChoices('email', 'e-mail')).

Example fix

// before
x: int = Field(validation_alias=['user', 'id'])
// after
from pydantic import AliasPath
x: int = Field(validation_alias=AliasPath('user', 'id'))
Defensive patterns

Strategy: type-guard

Validate before calling

from pydantic import AliasChoices, AliasPath

def coerce_validation_alias(v):
    if isinstance(v, (str, AliasChoices, AliasPath)):
        return v
    if isinstance(v, list):
        return AliasPath(*v)
    if isinstance(v, tuple):
        return AliasPath(*v)
    raise TypeError('Invalid validation_alias type')

Type guard

def is_valid_validation_alias(v) -> bool:
    from pydantic import AliasChoices, AliasPath
    return isinstance(v, (str, AliasChoices, AliasPath))

Try / catch

try:
    Field(validation_alias=v)
except TypeError as e:
    if 'validation_alias' in str(e):
        from pydantic import AliasPath
        return Field(validation_alias=AliasPath(*v))
    raise

Prevention

When it happens

Trigger: Calling Field(validation_alias=['a', 'b']) (a bare list instead of AliasPath); Field(validation_alias=re.compile('...')); passing a tuple or dict as validation_alias; helper code that forwards arbitrary objects.

Common situations: Migrating from v1's regex aliases; building aliases programmatically and forgetting to wrap paths in AliasPath; confusing AliasChoices (multiple keys, any matches) with AliasPath (nested path) semantics.

Related errors


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