Skip to content

Poor error messages when validating a discriminated Union of a "type statement".  #11043

@cj81499

Description

@cj81499

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

When validating a discriminated Union of a "type statement", the errors are far worse than when not using a "type statement", making it very difficult to understand why the value failed validation.

It seems like pydantic is duplicating/nesting the type, since the (undesirable) output contains "tagged-union[union[A,B],union[A,B]]", rather than "tagged-union[A,B]" (as found in the output when not using a type statement). Additionally, we see A.A.extra_field instead of A.extra_field.

Possibly related to #6352.

Example Code

from typing import Annotated, Literal

import pydantic


class _Base(pydantic.BaseModel):
    model_config = pydantic.ConfigDict(extra="forbid")

class A(_Base):
    type: Literal["A"] = "A"
    val: int

class B(_Base):
    type: Literal["B"] = "B"
    val: str

type _U = A | B
U = Annotated[_U, pydantic.Field(discriminator="type")]
U_ADAPTER = pydantic.TypeAdapter[U](U)

U_ADAPTER.validate_python({"type": "A", "val": 1, "extra_field": "oops!"})

Output:

Traceback (most recent call last):
  File "<REDACTED_PATH>/pydantic_playground.py", line 23, in <module>
    U_ADAPTER.validate_python({"type": "A", "val": 1, "extra_field": "oops!"})
  File "<REDACTED_PATH>/.venv/lib/python3.12/site-packages/pydantic/type_adapter.py", line 144, in wrapped
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<REDACTED_PATH>/.venv/lib/python3.12/site-packages/pydantic/type_adapter.py", line 375, in validate_python
    return self.validator.validate_python(object, strict=strict, from_attributes=from_attributes, context=context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 4 validation errors for tagged-union[union[A,B],union[A,B]]
A.A.extra_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='oops!', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden
A.B.type
  Input should be 'B' [type=literal_error, input_value='A', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/literal_error
A.B.val
  Input should be a valid string [type=string_type, input_value=1, input_type=int]
    For further information visit https://errors.pydantic.dev/2.9/v/string_type
A.B.extra_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='oops!', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbid

Replacing type _U = A | B with _U = A | B, the error is much improved:

Traceback (most recent call last):
  File "<REDACTED_PATH>/pydantic_playground.py", line 21, in <module>
    U_ADAPTER.validate_python({"type": "A", "val": 1, "extra_field": "oops!"})
  File "<REDACTED_PATH>/.venv/lib/python3.12/site-packages/pydantic/type_adapter.py", line 144, in wrapped
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<REDACTED_PATH>/.venv/lib/python3.12/site-packages/pydantic/type_adapter.py", line 375, in validate_python
    return self.validator.validate_python(object, strict=strict, from_attributes=from_attributes, context=context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 1 validation error for tagged-union[A,B]
A.extra_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='oops!', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden

Python, Pydantic & OS Version

             pydantic version: 2.9.0
        pydantic-core version: 2.23.2
          pydantic-core build: profile=release pgo=false
                 install path: <REDACTED_PATH>/.venv/lib/python3.12/site-packages/pydantic
               python version: 3.12.7 (main, Oct  2 2024, 16:35:10) [Clang 18.1.8 ]
                     platform: Linux-5.4.0-131-generic-x86_64-with-glibc2.31
             related packages: fastapi-0.115.2 mypy-1.13.0 typing_extensions-4.12.2
                       commit: unknown

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions