Jump to solution
Verify

The Fix

pip install pydantic==1.10.20

Based on closed pydantic/pydantic issue #11220 · PR/commit linked

Jump to Verify Open PR/Commit
@@ -11,7 +11,7 @@ from functools import lru_cache, partial from types import FunctionType -from typing import Any, Callable, Generic, Literal, NoReturn, TypeVar, cast +from typing import Any, Callable, Generic, Literal, NoReturn, cast
repro.py
from typing import Generic, TypeVar from pydantic import BaseModel A = TypeVar("A") B = TypeVar("B") C = TypeVar("C") class M1(BaseModel, Generic[A, B]): pass class M2(M1[int, C], Generic[C]): pass class M3(M2[str]): pass def test_mro(): assert M2.mro() == [ # Works in latest version M2, M1[int, C], M1, BaseModel, Generic, object, ] assert M3.mro() == [ M3, M2[str], M2, # But this fails in Pydantic 2.10.x. # It is incorrectly as "M1[int, str]" although there is no such generic being used in subclasses. M1[int, C], M1, BaseModel, Generic, object, ] # Seems issue is related to broken __pydantic_generic_metadata__ when using mro def test_generic_meta(): expected_meta = {"args": (int, C), "origin": M1, "parameters": (C,)} # These work in latest version assert M1[int, C].__pydantic_generic_metadata__ == expected_meta assert M2.mro()[1].__pydantic_generic_metadata__ == expected_meta # But this is broken after Pydantic 2.10.x. assert M3.mro()[3].__pydantic_generic_metadata__ == expected_meta def test_generic_meta_full(): assert [(c.__name__, getattr(c, "__pydantic_generic_metadata__", None)) for c in M3.mro()] == [ ("M3", {"args": (), "origin": None, "parameters": ()}), ("M2[str]", {"args": (str,), "origin": M2, "parameters": ()}), ("M2", {"args": (), "origin": None, "parameters": (C,)}), ("M1[int, TypeVar]", {"args": (int, C), "origin": M1, "parameters": (C,)}), # Broken in Pydantic 2.10.x ("M1", {"args": (), "origin": None, "parameters": (A, B)}), ("BaseModel", None), ("Generic", None), ("object", None), ]
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Upgrade to fixed release\npip install pydantic==1.10.20\nWhen NOT to use: This fix should not be applied if custom MRO behavior is required for specific use cases.\n\n

Why This Fix Works in Production

  • Trigger: MRO broken after 2.10.x with subclassed generics
  • Mechanism: The custom MRO implementation of Pydantic models was no longer necessary due to previous changes
  • Why the fix works: Removed the custom MRO implementation of Pydantic models, which is no longer necessary due to previous changes. (first fixed release: 1.10.20).

Why This Breaks in Prod

  • Shows up under Python 3.12 in real deployments (not just unit tests).
  • The custom MRO implementation of Pydantic models was no longer necessary due to previous changes
  • Production symptom (often without a traceback): MRO broken after 2.10.x with subclassed generics

Proof / Evidence

Verified Execution

We executed the runnable minimal repro in a temporary environment and captured exit codes + logs.

  • Status: PASS
  • Ran: 2026-02-11T16:52:29Z
  • Package: pydantic
  • Fixed: 1.10.20
  • Mode: fixed_only
  • Outcome: ok
Logs
affected (exit=None)
fixed (exit=0)

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“Might be fixed by https://github.com/pydantic/pydantic/pull/11184 When can we get it released?”
@MarkusSintonen · 2025-01-05 · confirmation · source
“> Might be fixed by https://github.com/pydantic/pydantic/pull/11184 Yes! I confirmed with main that the regression has been fixed by this ^. Do we have unit tests…”
@MarkusSintonen · 2025-01-05 · source
“Thanks @Viicos, when can we get next patch release? About tests, I was just thinking about some tests for mro but if we expect no…”
@MarkusSintonen · 2025-01-07 · source
“Yes the MRO approach taken in https://github.com/pydantic/pydantic/pull/10100 was something I wanted to replace since we saw regressions in 2.10”
@Viicos · 2025-01-05 · source

Failure Signature (Search String)

  • MRO broken after 2.10.x with subclassed generics
  • assert M2.mro() == [ # Works in latest version
Copy-friendly signature
signature.txt
Failure Signature ----------------- MRO broken after 2.10.x with subclassed generics assert M2.mro() == [ # Works in latest version

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- MRO broken after 2.10.x with subclassed generics assert M2.mro() == [ # Works in latest version

Minimal Reproduction

repro.py
from typing import Generic, TypeVar from pydantic import BaseModel A = TypeVar("A") B = TypeVar("B") C = TypeVar("C") class M1(BaseModel, Generic[A, B]): pass class M2(M1[int, C], Generic[C]): pass class M3(M2[str]): pass def test_mro(): assert M2.mro() == [ # Works in latest version M2, M1[int, C], M1, BaseModel, Generic, object, ] assert M3.mro() == [ M3, M2[str], M2, # But this fails in Pydantic 2.10.x. # It is incorrectly as "M1[int, str]" although there is no such generic being used in subclasses. M1[int, C], M1, BaseModel, Generic, object, ] # Seems issue is related to broken __pydantic_generic_metadata__ when using mro def test_generic_meta(): expected_meta = {"args": (int, C), "origin": M1, "parameters": (C,)} # These work in latest version assert M1[int, C].__pydantic_generic_metadata__ == expected_meta assert M2.mro()[1].__pydantic_generic_metadata__ == expected_meta # But this is broken after Pydantic 2.10.x. assert M3.mro()[3].__pydantic_generic_metadata__ == expected_meta def test_generic_meta_full(): assert [(c.__name__, getattr(c, "__pydantic_generic_metadata__", None)) for c in M3.mro()] == [ ("M3", {"args": (), "origin": None, "parameters": ()}), ("M2[str]", {"args": (str,), "origin": M2, "parameters": ()}), ("M2", {"args": (), "origin": None, "parameters": (C,)}), ("M1[int, TypeVar]", {"args": (int, C), "origin": M1, "parameters": (C,)}), # Broken in Pydantic 2.10.x ("M1", {"args": (), "origin": None, "parameters": (A, B)}), ("BaseModel", None), ("Generic", None), ("object", None), ]

Environment

  • Python: 3.12
  • Pydantic: 2

What Broke

MRO produced incorrect results for subclassed generics, leading to unexpected behavior.

Why It Broke

The custom MRO implementation of Pydantic models was no longer necessary due to previous changes

Fix Options (Details)

Option A — Upgrade to fixed release Safe default (recommended)

pip install pydantic==1.10.20

When NOT to use: This fix should not be applied if custom MRO behavior is required for specific use cases.

Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.

Fix reference: https://github.com/pydantic/pydantic/pull/11184

First fixed release: 1.10.20

Last verified: 2026-02-09. Validate in your environment.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • This fix should not be applied if custom MRO behavior is required for specific use cases.

Verify Fix

verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.

Did This Fix Work in Your Case?

Quick signal helps us prioritize which fixes to verify and improve.

Prevention

  • Add a CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
  • Upgrade behind a canary and run integration tests against the canary before 100% rollout.

Version Compatibility Table

VersionStatus
1.10.20 Fixed

Related Issues

No related fixes found.

Sources

We don’t republish the full GitHub discussion text. Use the links above for context.