The Fix
pip install pydantic==2.11.2
Based on closed pydantic/pydantic issue #11675 · PR/commit linked
@@ -290,7 +290,7 @@ def to_argument(
strict = model_strict if self.strict is None else self.strict
if typed or strict:
- type_annotation = self.expand_type(current_info, api)
+ type_annotation = self.expand_type(current_info, api, include_root_type=True)
else:
from typing import reveal_type
from pydantic import RootModel, BaseModel
class A(RootModel[list[int]]):
pass
class B(BaseModel):
a: A
class C(B):
pass
b = B(a=A([1, 2, 3]))
c = C(a=A([1, 2, 3]))
reveal_type(b.a) # A (expected)
reveal_type(c.a) # A | list[int] (unexpected, should be A)
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==2.11.2\nWhen NOT to use: Do not apply this fix if the mypy plugin is not being used with Pydantic.\n\n
Why This Fix Works in Production
- Trigger: reveal_type(c.a) # A | list[int] (unexpected, should be A)
- Mechanism: Root models were incorrectly inferred as unions by mypy when using the Pydantic plugin
- Why the fix works: Fixes an issue where root models were incorrectly inferred as unions by mypy when using the Pydantic plugin. (first fixed release: 2.11.2).
- If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).
Why This Breaks in Prod
- Root models were incorrectly inferred as unions by mypy when using the Pydantic plugin
- Production symptom (often without a traceback): reveal_type(c.a) # A | list[int] (unexpected, should be A)
Proof / Evidence
- GitHub issue: #11675
- Fix PR: https://github.com/pydantic/pydantic/pull/11676
- First fixed release: 2.11.2
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.95
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.61
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“### Initial Checks - [x] I confirm that I'm using Pydantic V2 ### Description Maybe related to #11657. In the example below, Pyright 1.1.398 deduces A for both b.a and c.a, while mypy (with the Pydantic plugin) deduces the union type for c.”
Failure Signature (Search String)
- reveal_type(c.a) # A | list[int] (unexpected, should be A)
Copy-friendly signature
Failure Signature
-----------------
reveal_type(c.a) # A | list[int] (unexpected, should be A)
Error Message
Signature-only (no traceback captured)
Error Message
-------------
reveal_type(c.a) # A | list[int] (unexpected, should be A)
Minimal Reproduction
from typing import reveal_type
from pydantic import RootModel, BaseModel
class A(RootModel[list[int]]):
pass
class B(BaseModel):
a: A
class C(B):
pass
b = B(a=A([1, 2, 3]))
c = C(a=A([1, 2, 3]))
reveal_type(b.a) # A (expected)
reveal_type(c.a) # A | list[int] (unexpected, should be A)
Environment
- Pydantic: 2
What Broke
Mypy incorrectly deduces union types, leading to type errors in code.
Why It Broke
Root models were incorrectly inferred as unions by mypy when using the Pydantic plugin
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install pydantic==2.11.2
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/11676
First fixed release: 2.11.2
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not apply this fix if the mypy plugin is not being used with Pydantic.
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 |
|---|---|
| 2.11.2 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.