The Fix
pip install pydantic==1.10.20
Based on closed pydantic/pydantic issue #11220 · PR/commit linked
@@ -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
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),
]
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
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
- GitHub issue: #11220
- Fix PR: https://github.com/pydantic/pydantic/pull/11184
- First fixed release: 1.10.20
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.85
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.41
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
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?”
“> 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…”
“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…”
“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”
Failure Signature (Search String)
- MRO broken after 2.10.x with subclassed generics
- assert M2.mro() == [ # Works in latest version
Copy-friendly signature
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 Message
-------------
MRO broken after 2.10.x with subclassed generics
assert M2.mro() == [ # Works in latest version
Minimal Reproduction
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
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.
When NOT to Use This Fix
- This fix should not be applied if custom MRO behavior is required for specific use cases.
Verify Fix
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
| Version | Status |
|---|---|
| 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.