pypa/pip · error · TypeError
Cannot restore Specifier from {state!r}
Error message
Cannot restore Specifier from {state!r} What it means
Raised as TypeError (specifiers.py:802) inside Specifier.__setstate__ when the pickled state matches none of the recognized formats: new tuple ((operator, version), prereleases), the 26.0-26.1 slot-dict tuple, or the legacy plain dict. It is the fail-closed branch for corrupt or foreign Specifier pickles.
Source
Thrown at src/pip/_vendor/packaging/specifiers.py:802
if len(state) == 2 and isinstance(state[1], dict):
# Format (packaging 26.0-26.1): (None, {slot: value}).
_, slot_dict = state
spec = slot_dict.get("_spec")
prereleases = slot_dict.get("_prereleases", "invalid")
if _validate_spec(spec) and _validate_pre(prereleases):
self._spec = spec
self._prereleases = prereleases
return
if isinstance(state, dict):
# Old format (packaging <= 25.x, no __slots__): state is a plain dict.
spec = state.get("_spec")
prereleases = state.get("_prereleases", "invalid")
if _validate_spec(spec) and _validate_pre(prereleases):
self._spec = spec
self._prereleases = prereleases
return
raise TypeError(f"Cannot restore Specifier from {state!r}")
@property
def operator(self) -> str:
"""The operator of this specifier.
>>> Specifier("==1.2.3").operator
'=='
"""
return self._spec[0]
@property
def version(self) -> str:
"""The version of this specifier.
>>> Specifier("==1.2.3").version
'1.2.3'
"""
return self._spec[1]View on GitHub (pinned to d7d0d0a394)
Solutions
- Discard the pickle and reconstruct the Specifier from its string form via Specifier(str(...)).
- Align producer and consumer packaging versions so __getstate__/__setstate__ agree.
- Avoid pickling Specifier across processes with different vendored packaging copies.
Example fix
# before
spec = pickle.load(open("s.pkl", "rb")) # TypeError
# after
try:
spec = pickle.load(open("s.pkl", "rb"))
except TypeError:
from pip._vendor.packaging.specifiers import Specifier
spec = Specifier(open("spec.txt").read().strip()) Defensive patterns
Strategy: try-catch
Validate before calling
from typing import Any
def is_recognized_specifier_state(state):
# new: ((op, ver), prereleases) ; legacy slot: (None, dict) ; legacy: dict
if isinstance(state, tuple) and len(state) == 2:
return True
if isinstance(state, dict):
return True
return False Type guard
null
Try / catch
import pickle
from pip._vendor.packaging.specifiers import Specifier
try:
spec = pickle.load(open(path, 'rb'))
except TypeError as e:
if 'Cannot restore Specifier' in str(e):
spec = Specifier(open('spec.txt').read().strip()) Prevention
- Persist Specifier as its string form rather than as a pickle.
- Keep producer and consumer packaging versions aligned for pickle exchange.
When it happens
Trigger: pickle.load on a Specifier whose state has been altered, truncated, or produced by a non-standard __getstate__. Reached only after all three format-detection branches decline the state.
Common situations: Cross-version pickle sharing where the producer's packaging is neither the new 26.2+ format nor one of the recognized legacy ones (e.g. a custom subclass). Manual tampering with pickle bytes. A pickle from a different Specifier implementation.
Related errors
- Cannot restore SpecifierSet from {state!r}
- Cannot restore {self.__class__.__name__} value from {value!r
- Cannot restore Requirement from {state!r}
- Cannot restore Tag from {state!r}
- Cannot restore {self.__class__.__name__} from {state!r}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/e12bb059e8493c28.json.
Report an issue: GitHub.