pypa/pip · error · TypeError
Cannot restore Marker from {state!r}
Error message
Cannot restore Marker from {state!r} What it means
Raised as TypeError from Marker.__setstate__ when unpickling/copying a Marker whose pickled state is the new (packaging 26.2+) string format, but that string cannot be re-parsed by _parse_marker (raises ParserSyntaxError). The string was supposed to be a valid PEP 508 marker expression but is malformed when restored.
Source
Thrown at src/pip/_vendor/packaging/markers.py:405
def __eq__(self, other: object) -> bool:
if not isinstance(other, Marker):
return NotImplemented
return str(self) == str(other)
def __getstate__(self) -> str:
# Return the marker expression string for compactness and stability.
# Internal Node objects are excluded; the string is re-parsed on load.
return str(self)
def __setstate__(self, state: object) -> None:
if isinstance(state, str):
# New format (26.2+): just the marker expression string.
try:
self._markers = _normalize_extra_values(_parse_marker(state))
except ParserSyntaxError as exc:
raise TypeError(f"Cannot restore Marker from {state!r}") from exc
return
if isinstance(state, dict) and "_markers" in state:
# Old format (packaging <= 26.1, no __slots__): plain __dict__.
markers = state["_markers"]
if isinstance(markers, list):
self._markers = markers
return
if isinstance(state, tuple) and len(state) == 2:
# Old format (packaging <= 26.1, __slots__): (None, {slot: value}).
_, slot_dict = state
if isinstance(slot_dict, dict) and "_markers" in slot_dict:
markers = slot_dict["_markers"]
if isinstance(markers, list):
self._markers = markers
return
raise TypeError(f"Cannot restore Marker from {state!r}")
def __and__(self, other: Marker) -> Marker:View on GitHub (pinned to d7d0d0a394)
Solutions
- Regenerate the Marker from its source string with Marker(expr) instead of unpickling a stale object.
- If caching, store the marker expression string and reconstruct Marker(...) on load rather than pickling the object.
- Catch TypeError around pickle.loads / copy operations and rebuild the Marker from the original expression.
- Validate the cached string with Marker(str) before persisting, so corrupt data is never written.
Example fix
# before import pickle m = pickle.loads(cached_bytes) # after expr = load_expression_string_from_cache() m = Marker(expr)
Defensive patterns
Strategy: try-catch
Validate before calling
from packaging.markers import Marker
from packaging.markers import ParserSyntaxError
def validate_marker_string(s: str) -> bool:
try:
Marker(s)
return True
except ParserSyntaxError:
return False Try / catch
import pickle
try:
m = pickle.loads(data)
except TypeError as e:
if 'Cannot restore Marker' in str(e):
m = Marker(stored_expr_str)
else:
raise Prevention
- Cache the marker expression string, not the Marker object.
- Validate expression strings with Marker(s) before persisting.
- Pin packaging versions across processes sharing pickles.
- Catch TypeError around unpickle to rebuild from the source string.
When it happens
Trigger: Unpickling a Marker object whose serialized expression string got corrupted (e.g. truncated in a cache, mutated in a database). Using copy.deepcopy on a Marker whose __getstate__ returned a non-expression string subclass. Loading a pickle produced by a buggy custom __reduce__.
Common situations: Cross-process caches (multiprocessing, redis) storing pickled Marker objects; rolling a cache forward/backward across packaging versions; test fixtures with hand-edited pickle bytes.
Related errors
- Cannot restore {self.__class__.__name__} value from {value!r
- Cannot restore Requirement from {state!r}
- Cannot restore Specifier from {state!r}
- Cannot restore SpecifierSet from {state!r}
- Cannot restore Tag from {state!r}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/5e9b4171bf9484c3.json.
Report an issue: GitHub.