Skip to content

Pydantic 2.5.0 regressed Discriminated Unions usage with DotEnvSettingsSource and forbidden extra #439

@pszpetkowski

Description

@pszpetkowski

I haven't tested the latest main, but I'm pretty sure the issue is still not fixed.

#386 introduced a regression which breaks what worked under 2.4.0. The problem probably is the new condition lenient_issubclass(field.annotation, BaseModel) and env_name.startswith(field_env_name) that cannot work for Union fields -- just simple BaseModel.

It causes the following to result in error:

from typing import Annotated, Literal
import pydantic
import pydantic_settings


class Cat(pydantic.BaseModel):
    pet_type: Literal["cat"]
    sound: str


class Dog(pydantic.BaseModel):
    pet_type: Literal["dog"]
    sound: str


class Settings(pydantic_settings.BaseSettings):
    model_config = pydantic_settings.SettingsConfigDict(
        env_file=".env", env_prefix="FOO_", env_nested_delimiter="-", extra="forbid"
    )
    pet: Annotated[Cat | Dog, pydantic.Field(discrimator="pet_type")]


print(Settings())

With the following configuration provided with .env file:

FOO_PET-SOUND="woof"
FOO_PET-PET_TYPE="dog"

Under pydantic-settings 2.5.2 it results in the following error:

pydantic_core._pydantic_core.ValidationError: 2 validation errors for Settings
foo_pet-sound
  Extra inputs are not permitted [type=extra_forbidden, input_value='woof', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden
foo_pet-pet_type
  Extra inputs are not permitted [type=extra_forbidden, input_value='dog', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden

Under pydantic-settings 2.4.0 I'm getting the correct result:

pet=Dog(pet_type='dog', sound='woof')

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions