The Fix
pip install pydantic==2.11.5
Based on closed pydantic/pydantic issue #11849 · PR/commit linked
Production note: This tends to surface only under concurrency. Reproduce with load tests and watch for lock contention/cancellation paths.
@@ -620,9 +620,11 @@ def model_rebuild(
for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'):
- if attr in cls.__dict__:
+ if attr in cls.__dict__ and not isinstance(getattr(cls, attr), _mock_val_ser.MockValSer):
# Deleting the validator/serializer is necessary as otherwise they can get reused in
from __future__ import annotations # support forward refs
from pydantic import BaseModel , model_validator, ValidationInfo
from typing import Self
class Direct(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str
description: Optional[Translatable] = None
...
class Translatable(BaseModel):
en: str = ""
...
d = Direct(id="test", description=Translatable(en="ok")) # raises PydanticUserError("Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly")
# The translatable was intantiated correctly, but `Direct` seems do BE BaseModel
# second example
class A(BaseModel):
@model_validator(mode="after")
def _modelAfterValidator(self, info: ValidationInfo) -> Self:
...
return self
class B(A):
id: str
class C(B):
name: str | None = None
forward: Foo | None = None
class Foo:
pass
c1 = C.model_validate({"name": "test", "id": "ok1"}) # correctly instantiates
c2 = C.model_validate({"name": "test", "id": "ok2"}) # correctly instantiates
c3 = C.model_validate({"name": "test", "id": "ok3"}) # correctly instantiates
print(c1) # B(id="ok1") __repr__ shows class B instead of C!!!
print(c2) # B(id="ok2")
c1.name # raises AttributeError("'B' object has no attribute 'name'"). again B instead of C
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.5\nWhen NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.\n\nOption C — Workaround\nfor now, but not a safe permanent fix, or something easily done at scale in large repos.\nWhen NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.\n\n
Why This Fix Works in Production
- Trigger: (race condition?) Subclass skipped in model instantiation
- Mechanism: A race condition in model instantiation caused models to be skipped during initialization
- Why the fix works: Addresses a race condition in model instantiation by ensuring that mock validators/serializers are not deleted prematurely during model rebuilds. (first fixed release: 2.11.5).
- If left unfixed, failures can be intermittent under concurrency (hard to reproduce; shows up as sporadic 5xx/timeouts).
Why This Breaks in Prod
- Shows up under Python 3.13 in real deployments (not just unit tests).
- A race condition in model instantiation caused models to be skipped during initialization
- Production symptom (often without a traceback): (race condition?) Subclass skipped in model instantiation
Proof / Evidence
- GitHub issue: #11849
- Fix PR: https://github.com/pydantic/pydantic/pull/11890
- First fixed release: 2.11.5
- 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.45
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Hi. Managed to semi-reliably reproduce when using threads, see https://github.com/raulparada/pydantic-repro-11849. I'll try making it clearer / getting the parameters right (I'm getting the error just…”
“Couldn't manage to make it fail more reliably but maybe a kind soul with more understanding of threading (/pydantic) can help hit the sweet spot,…”
“I'm >150 iterations on https://github.com/pydantic/pydantic/commit/f43102e8a3ac1d7ce0e341a3bdb495478780ba02 without seeing the issue, so promising @Viicos! 🎉 update: >600 and still no issue, seems fixed”
“While anecdotal I can confirm we have been hitting very similar issues”
Failure Signature (Search String)
- (race condition?) Subclass skipped in model instantiation
- [to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]
Copy-friendly signature
Failure Signature
-----------------
(race condition?) Subclass skipped in model instantiation
[to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]
Error Message
Signature-only (no traceback captured)
Error Message
-------------
(race condition?) Subclass skipped in model instantiation
[to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]
Minimal Reproduction
from __future__ import annotations # support forward refs
from pydantic import BaseModel , model_validator, ValidationInfo
from typing import Self
class Direct(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str
description: Optional[Translatable] = None
...
class Translatable(BaseModel):
en: str = ""
...
d = Direct(id="test", description=Translatable(en="ok")) # raises PydanticUserError("Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly")
# The translatable was intantiated correctly, but `Direct` seems do BE BaseModel
# second example
class A(BaseModel):
@model_validator(mode="after")
def _modelAfterValidator(self, info: ValidationInfo) -> Self:
...
return self
class B(A):
id: str
class C(B):
name: str | None = None
forward: Foo | None = None
class Foo:
pass
c1 = C.model_validate({"name": "test", "id": "ok1"}) # correctly instantiates
c2 = C.model_validate({"name": "test", "id": "ok2"}) # correctly instantiates
c3 = C.model_validate({"name": "test", "id": "ok3"}) # correctly instantiates
print(c1) # B(id="ok1") __repr__ shows class B instead of C!!!
print(c2) # B(id="ok2")
c1.name # raises AttributeError("'B' object has no attribute 'name'"). again B instead of C
Environment
- Python: 3.13
- Pydantic: 2
What Broke
Models occasionally fail to initialize correctly, leading to runtime errors in production.
Why It Broke
A race condition in model instantiation caused models to be skipped during initialization
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install pydantic==2.11.5
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Option C — Workaround Temporary workaround
for now, but not a safe permanent fix, or something easily done at scale in large repos.
Use only if you cannot change versions today. Treat this as a stopgap and remove once upgraded.
Fix reference: https://github.com/pydantic/pydantic/pull/11890
First fixed release: 2.11.5
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix should not be applied if the application does not use multi-threading or multi-processing.
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.
- Add a TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
- Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.
Version Compatibility Table
| Version | Status |
|---|---|
| 2.11.5 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.