pypa/pip · error · TypeError
Cannot restore Version from
Error message
Cannot restore Version from {state!r} What it means
Raised by Version.__setstate__ during unpickling when the saved state does not match any known pickle format: the 6-tuple (epoch, release, pre, post, dev, local) used by packaging 26.2+, the 2-tuple (None, slot_dict) from 26.0-26.1, or the legacy dict format from packaging <= 25.x. If none of these shapes is recognized, unpickling cannot proceed and TypeError is raised. This protects against restoring a Version from corrupted or foreign pickle data.
Solutions
- Re-serialize the Version objects with the current packaging version to regenerate a compatible pickle.
- Avoid pickling Version objects across packaging major versions; store the version as a string and reconstruct with Version(str).
- If migrating, decode old pickles by extracting the version string and re-creating the Version instance.
Example fix
// before
# old cache: pickle.load(f) containing pre-26.2 Version with unknown state
// after
# store version strings instead of Version objects in the cache
with open(cache, 'w') as f:
json.dump(str(v), f)
# later: v = Version(pickle.load_or_json_string) Defensive patterns
Strategy: validation
Validate before calling
# Before unpickling, store/retrieve version strings instead of Version objects # v = Version(pickle.load(f)) # reconstruct from string, not unpickle the object
Try / catch
try:
obj = pickle.load(f)
except TypeError as e:
if 'Cannot restore Version' in str(e):
# regenerate from a stored string representation
obj = None Prevention
- Don't pickle Version objects across packaging major versions.
- Store versions as strings in caches/databases and reconstruct at load time.
- Invalidate caches when upgrading the packaging library.
When it happens
Trigger: Unpickling a Version object from a pickle file/stream whose state tuple/dict was manually constructed, truncated, or written by a completely different (non-packaging) serialization scheme. Also possible if a future format change introduces a shape not yet handled.
Common situations: Loading a stale cache or joblib/cloudpickle artifact that contains a Version serialized by an incompatible or much older/newer packaging version; passing a hand-built state to a Version via copy.copy/copy.deepcopy with a patched __reduce__.
Related errors
- Cannot restore Requirement from
- Cannot restore Specifier from
- Cannot restore SpecifierSet from
- Cannot restore Tag from
- Cannot restore Marker from
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/f6d22606cb705a4e.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/version.py:833
self._pre = slot_dict.get("_pre")
self._post = slot_dict.get("_post")
self._dev = slot_dict.get("_dev")
self._local = slot_dict.get("_local")
return
if isinstance(state, dict):
# Old format (packaging <= 25.x, no __slots__): state is a plain
# dict with "_version" (_Version NamedTuple) and "_key" entries.
version_nt = state.get("_version")
if version_nt is not None:
self._epoch = version_nt.epoch
self._release = version_nt.release
self._pre = version_nt.pre
self._post = version_nt.post
self._dev = version_nt.dev
self._local = version_nt.local
return
raise TypeError(f"Cannot restore Version from {state!r}")
@property
@_deprecated("Version._version is private and will be removed soon")
def _version(self) -> _Version:
return _Version(
self._epoch, self._release, self._dev, self._pre, self._post, self._local
)
@_version.setter
@_deprecated("Version._version is private and will be removed soon")
def _version(self, value: _Version) -> None:
self._epoch = value.epoch
self._release = value.release
self._dev = value.dev
self._pre = value.pre
self._post = value.post
self._local = value.local
self._key_cache = NoneView on GitHub (pinned to f399c37189)