Skip to content

upstream(pydantic): model_config merges last-wins across bases, not MRO #138

Open

Description

@cdwilson

Tracks upstream friction in Pydantic. The explanation lives in the docs; this issue is the unit of work.

Explanation: model_config merges across bases in "last wins" order, not MRO — the limitation, why it matters to an ODM, the workaround tinydantic carries, and the change that would remove it. That section is written to be read standalone by an upstream maintainer, so it doubles as the ready-to-send proposal if we ever file this.

Reproduction

Upstream only — no tinydantic import, so this is what a report would carry.

from pydantic import BaseModel, ConfigDict


class A(BaseModel):
    model_config = ConfigDict(strict=True)


class B(BaseModel):
    model_config = ConfigDict(strict=False)


class C(A, B):
    pass


print("MRO:                   ", [k.__name__ for k in C.__mro__])
print("C.model_config['strict']:", C.model_config["strict"])

Run with python repro.py.

Actual output:

MRO:                    ['C', 'A', 'B', 'BaseModel', 'object']
C.model_config['strict']: False

A precedes B in the MRO, so every other attribute on C resolves through A. Only model_config resolves through B, because Pydantic walks the bases left to right and lets each overwrite what came before. Nothing warns that the two orderings disagree.

Expected: True — model_config merges in MRO order (for base in reversed(cls.__mro__)), so config resolution matches every other attribute on the class. Failing that, a warning at class-creation time when two bases set the same key to different values.

Environment: pydantic 2.13.4, Python 3.10.20, macOS. Run 2026-08-13. The same result holds on the 2.11 floor.

What tinydantic carries today

tinydantic keeps its configuration out of model_config entirely: each class stores only its own keys in __tinydantic_config__, and lookup walks cls.__mro__. Where two unrelated bases genuinely conflict, AmbiguousConfigError is raised at class-definition time rather than guessing. See src/tinydantic/_config.py.

Cost: tinydantic config does not appear in model_config, so users have two config surfaces to learn.

Upstream status

Already tracked upstream as pydantic#9992 (open, v3 milestone). Nothing to file — this issue tracks our side.

What would close this

Pydantic merging model_config in MRO order, or the non-breaking interim step of warning when two bases set the same key to different values — or a maintainer decision to carry the workaround indefinitely.

Assisted-by: Claude:claude-opus-5

Activity

  1. added
    enhancementNew feature or request
    upstreamTracks a defect or request in an upstream dependency
    ai-assistedCreated or investigated with help from an AI agent
    on Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai-assistedCreated or investigated with help from an AI agentenhancementNew feature or requestupstreamTracks a defect or request in an upstream dependency

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions