pydantic/pydantic · error · PydanticUserError
discriminator-alias-type
discriminator-alias-type
Error message
Alias {alias!r} is not supported in a discriminated union What it means
Pydantic raises this PydanticUserError (code 'discriminator-alias-type') when the discriminator field on a union member has a validation_alias that is not a plain string — for example an AliasChoices list, an AliasPath tuple, or any tuple/list-valued alias. The discriminated-union machinery at _infer_discriminator_values_for_field (line 417-421) reads field.get('validation_alias', self.discriminator) and requires it to be a str so it can be used as a single lookup key in the tagged-union schema. Complex alias paths cannot serve as a discriminator key.
Source
Thrown at pydantic/_internal/_discriminated_union.py:419
self, choice: core_schema.DataclassArgsSchema, source_name: str | None = None
) -> list[str | int]:
source = 'DataclassArgs' if source_name is None else f'Dataclass {source_name!r}'
for field in choice['fields']:
if field['name'] == self.discriminator:
break
else:
raise PydanticUserError(
f'{source} needs a discriminator field for key {self.discriminator!r}', code='discriminator-no-field'
)
return self._infer_discriminator_values_for_field(field, source)
def _infer_discriminator_values_for_field(self, field: CoreSchemaField, source: str) -> list[str | int]:
if field['type'] == 'computed-field':
# This should never occur as a discriminator, as it is only relevant to serialization
return []
alias = field.get('validation_alias', self.discriminator)
if not isinstance(alias, str):
raise PydanticUserError(
f'Alias {alias!r} is not supported in a discriminated union', code='discriminator-alias-type'
)
if self._discriminator_alias is None:
self._discriminator_alias = alias
elif self._discriminator_alias != alias:
raise PydanticUserError(
f'Aliases for discriminator {self.discriminator!r} must be the same '
f'(got {alias}, {self._discriminator_alias})',
code='discriminator-alias',
)
return self._infer_discriminator_values_for_inner_schema(field['schema'], source)
def _infer_discriminator_values_for_inner_schema(
self, schema: core_schema.CoreSchema, source: str
) -> list[str | int]:
"""When inferring discriminator values for a field, we typically extract the expected values from a literal
schema. This function does that, but also handles nested unions and defaults.
"""View on GitHub (pinned to 2e5f0e2b42)
Solutions
- Use a plain string validation_alias on the discriminator field: Field(validation_alias='kind').
- If the tag lives nested in your input, flatten the input before validation or use a pre-validator to hoist the value to the top level.
- Remove the alias entirely so the discriminator field uses its Python attribute name as the lookup key.
- Consider a callable Discriminator if the tag must be extracted via custom logic.
Example fix
// before
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(validation_alias=AliasPath('header', 'kind'))
// after
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(validation_alias='kind') Defensive patterns
Strategy: validation
Validate before calling
from pydantic.fields import AliasPath, AliasChoices
def check_discriminator_alias_simple(model_cls, field_name: str) -> None:
info = model_cls.model_fields[field_name]
alias = info.validation_alias
if alias is not None and not isinstance(alias, str):
raise TypeError(f'{model_cls.__name__}.{field_name} has non-string alias {alias!r}')
check_discriminator_alias_simple(Cat, 'pet_type') Type guard
def is_plain_alias(alias) -> bool:
return alias is None or isinstance(alias, str) Try / catch
from pydantic import PydanticUserError
try:
Pet.model_rebuild()
except PydanticUserError as e:
if e.code == 'discriminator-alias-type':
# replace AliasPath/AliasChoices on the discriminator with a plain str alias
... Prevention
- Never use AliasPath or AliasChoices on the discriminator field — keep it a plain string alias.
- If the tag is nested in input data, flatten it with a model_validator(mode='before') instead of an alias path.
- Review alias_generator output to ensure it returns a str for the discriminator field.
When it happens
Trigger: Annotating the discriminator field with Field(validation_alias=AliasPath('meta', 'kind')) or Field(validation_alias=AliasChoices('kind', 'type')) inside a member of a discriminated union. Also occurs when an alias_generator produces a non-string for the discriminator field name.
Common situations: Trying to read the discriminator value from a nested location in incoming JSON (e.g. AliasPath) rather than the top level. Reusing a model that has a generic alias generator that returns tuples for some fields.
Related errors
- discriminator-alias
- discriminator-validator
- discriminator-needs-literal
- Value {discriminator_value!r} for discriminator {self.discri
- validate-by-alias-and-name-false
AI-assisted analysis of pydantic/pydantic@2e5f0e2b42 (2026-08-04).
Data as JSON: /data/errors/f1e2070615e3a2df.json.
Report an issue: GitHub.