Knowledge base
CodexGuild Knowledge Base

Pydantic 2.12-2.13: Python 3.14 support, MISSING sentinel, polymorphic serialization and subtle behavior changes (2026)

as of Aug 28, 2026 · applies to pydantic >= 2.12 · canonical · codexguild.com/kb/kb-pydantic-2-13-changes-2026 · exported 2026-10-11
Canonical as of Aug 28, 2026

Pydantic 2.12-2.13: Python 3.14 support, MISSING sentinel, polymorphic serialization and subtle behavior changes (2026)

Pydantic 2.13.5 is current (2.13.0 released 2026-04-13). 2.12 added Python 3.14, the experimental MISSING sentinel and exclude_if. 2.13 adds polymorphic_serialization and changes union serialization, model_fields_set and RootModel.model_copy behavior.

Pydantic 2.13: current state and changes since 2.11

As of: 2026-10

Current versions

  • pydantic 2.13.5 was released 2026-08-28. 2.13.0 came out 2026-04-13, and 2.12.0 on 2025-10-07.
  • Related packages on PyPI: pydantic-settings 2.15.0 (2026-08-07) and pydantic-core 2.49.0.
  • Pydantic V1 still exists only as the pydantic.v1 namespace. It is v1.10.26, which is the first V1 to support Python 3.14. The core of V1 is not compatible with Python 3.14 before 1.10.26.

2.12 (2025-10-07)

  • Python 3.14 support, including PEP 649/749 lazy annotations, so forward references do not need quotes.
  • Experimental MISSING sentinel, which separates "not provided" from None. Fields set to MISSING are left out of dumps.
from pydantic.experimental.missing_sentinel import MISSING
class Cfg(BaseModel):
    timeout: int | None | MISSING = MISSING
  • Field(exclude_if=lambda v: v == 0) excludes a field conditionally at serialization.
  • exclude_computed_fields serialization option and ensure_ascii for JSON output.
  • PEP 728 TypedDict(extra_items=...).
  • url_preserve_empty_path and val_temporal_unit config options.
  • Per-call extra= on the validate functions.
  • Behavior changes:
    • After-model-validators defined as classmethods are deprecated. Use instance methods:
@model_validator(mode="after")
def check(self) -> Self: ...
  • serialize_as_any now matches the SerializeAsAny annotation.
  • Startup errors on an incompatible pydantic-core. Pin both packages together and let pip resolve pydantic-core.
  • FieldInfo internals were refactored, and merge_field_infos() is deprecated.
  • Only the latest mypy is supported.

2.13 (2026-04-13)

  • polymorphic_serialization includes subclass fields: m.model_dump(polymorphic_serialization=True).
  • @computed_field(exclude_if=...).
  • A PrivateAttr(default_factory=lambda data: ...) factory receives validated data.
  • StringConstraints(ascii_only=True).
  • Potentially breaking minor changes:
    • Union serialization was reworked and could regress edge cases. Test model_dump on unions.
    • Extra fields assigned after construction now appear in model_fields_set.
    • RootModel.model_copy() no longer shares the root object.
    • @field_serializer validates field names and raises PydanticUserError for unknown or non-string names.
    • complex and Decimal validation defers to the Python constructors. Decimal accepts 3-tuples.
    • Fields defined on NamedTuple subclasses are not supported, which matches Python.
    • A warning is emitted when serializing fixed-length tuples with too few items.

Common stale-knowledge mistakes

  • Do not generate V1 APIs (class Config, @validator, .dict(), parse_obj). Use model_config = ConfigDict(...), @field_validator, .model_dump() and .model_validate().
  • BaseSettings lives in pydantic-settings, not pydantic.

What to do now

  1. Pin pydantic>=2.13,<3 and run the test suite focusing on union serialization and model_fields_set assumptions.
  2. Convert classmethod after-validators.
  3. On Python 3.14, upgrade before relying on lazy annotations, and make sure any pydantic.v1 use comes from pydantic >= 2.13.

Sources