pypa/pip · error · TypeError
Cannot restore from
Error message
Cannot restore {self.__class__.__name__} from {state!r} What it means
Node.__setstate__ tries three known pickle formats when restoring during unpickling: the new compact string format (26.2+), the old __slots__ tuple format (<=26.0), and the old __dict__ format (<=25.0). If the state matches none of them, TypeError is raised with the unrecognizable state shown. This is a broader guard than error 265: it catches completely unrecognized state structures rather than just non-string values.
Solutions
- Serialize nodes to strings using serialize() and re-parse on load with parse_marker()/parse_requirement()
- Version your cache format and invalidate caches on packaging upgrades
- Catch TypeError and re-parse from the original source string as a fallback
Example fix
# before import pickle marker_node = pickle.loads(pickled_data) # incompatible format # after # Persist the serialized string form, not the Node object: # stored = marker_node.serialize() -> "python_version >= '3.8'" # On load, re-parse: from packaging._parser import parse_marker marker_node = parse_marker(stored_string)
Defensive patterns
Strategy: try-catch
Validate before calling
def safe_restore_node(pickled_data, original_source=None):
import pickle
try:
return pickle.loads(pickled_data)
except TypeError:
if original_source:
from packaging._parser import parse_marker
return parse_marker(original_source)
raise Type guard
def is_recognized_node_state(state) -> bool:
if isinstance(state, str):
return True
if isinstance(state, tuple) and len(state) == 2:
_, d = state
return isinstance(d, dict) and "value" in d
if isinstance(state, dict) and "value" in state:
return True
return False Try / catch
try:
node = pickle.loads(data)
except TypeError as e:
if "Cannot restore" in str(e):
from packaging._parser import parse_marker
node = parse_marker(original_req_string) Prevention
- Use string serialization (serialize()) for persistence, not pickling
- Version your cache format and invalidate on upgrades
- Store the original requirement string alongside cached objects
When it happens
Trigger: Unpickling a Variable, Value, or Op node from a pickle created by a future or incompatible version of packaging that uses a serialization format this version does not understand.
Common situations: Downgrading packaging after pickling nodes with a newer format. Loading cached data from a different packaging fork. Pickle protocol mismatches after environment changes.
Related errors
- Cannot restore value from
- Algorithm used in hash field has different value in hashes…
- Algorithm used in hash field is not present in hashes field
- Cannot restore Requirement from
- Cannot restore Specifier from
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/77f530b492ebe1bc.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/_parser.py:57
)
self.value = value
def __setstate__(self, state: object) -> None:
if isinstance(state, str):
# New format (26.2+): just the value string.
self._restore_value(state)
return
if isinstance(state, tuple) and len(state) == 2:
# Old format (packaging <= 26.0, __slots__): (None, {slot: value}).
_, slot_dict = state
if isinstance(slot_dict, dict) and "value" in slot_dict:
self._restore_value(slot_dict["value"])
return
if isinstance(state, dict) and "value" in state:
# Old format (packaging <= 25.0, no __slots__): plain __dict__.
self._restore_value(state["value"])
return
raise TypeError(f"Cannot restore {self.__class__.__name__} from {state!r}")
class Variable(Node):
__slots__ = ()
def serialize(self) -> str:
return str(self)
class Value(Node):
__slots__ = ()
def serialize(self) -> str:
value = str(self)
if '"' not in value:
return f'"{value}"'
if "'" not in value:
return f"'{value}'"View on GitHub (pinned to f399c37189)