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

  1. Re-serialize the Version objects with the current packaging version to regenerate a compatible pickle.
  2. Avoid pickling Version objects across packaging major versions; store the version as a string and reconstruct with Version(str).
  3. 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

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


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 = None

View on GitHub (pinned to f399c37189)