Skip to content

Discriminator field on BaseModel instances are incorrectly accessed by alias in validation #3846

@chornsby

Description

@chornsby

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and still think this is a bug

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

$ python -c "import pydantic.utils; print(pydantic.utils.version_info())"
             pydantic version: 1.9.0
            pydantic compiled: True
                 install path: ./venv/lib/python3.10/site-packages/pydantic
               python version: 3.10.2 (main, Jan 17 2022, 00:00:00) [GCC 11.2.1 20211203 (Red Hat 11.2.1-7)]
                     platform: Linux-5.16.9-200.fc35.x86_64-x86_64-with-glibc2.34
     optional deps. installed: ['typing-extensions']

When validating a discriminated union where the union value has been passed as a Pydantic model instance, it appears that the _validate_discriminated_union function is trying to access the value of the discriminator field via its alias. Since the alias does not exist on the model as an attribute, the validation fails.

I believe this is the result of a tiny mistake when setting up the _validate_discriminated_union function and that whenever a BaseModel or dataclass is detected then we should use the discriminator key and not the alias to access the discriminator value.

from typing import Literal, Union

from pydantic import BaseModel, Field


class A(BaseModel):
    literal: Literal['a'] = Field(alias='lit')

class B(BaseModel):
    literal: Literal['b'] = Field(alias='lit')

    class Config:
        allow_population_by_field_name = True

class Top(BaseModel):
    sub: Union[A, B] = Field(..., discriminator='literal')

Top(sub=A(lit='a'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)

Top(sub=B(lit='b'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)

Top(sub=B(literal='b'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug V1Bug related to Pydantic V1.X

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions