{"id":"f6d22606cb705a4e","repo":"pypa/pip","slug":"cannot-restore-version-from-state-r","errorCode":null,"errorMessage":"Cannot restore Version from {state!r}","messagePattern":"Cannot restore Version from (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/version.py","lineNumber":819,"sourceCode":"                    self._pre = slot_dict.get(\"_pre\")\n                    self._post = slot_dict.get(\"_post\")\n                    self._dev = slot_dict.get(\"_dev\")\n                    self._local = slot_dict.get(\"_local\")\n                    return\n        if isinstance(state, dict):\n            # Old format (packaging <= 25.x, no __slots__): state is a plain\n            # dict with \"_version\" (_Version NamedTuple) and \"_key\" entries.\n            version_nt = state.get(\"_version\")\n            if version_nt is not None:\n                self._epoch = version_nt.epoch\n                self._release = version_nt.release\n                self._pre = version_nt.pre\n                self._post = version_nt.post\n                self._dev = version_nt.dev\n                self._local = version_nt.local\n                return\n\n        raise TypeError(f\"Cannot restore Version from {state!r}\")\n\n    @property\n    @_deprecated(\"Version._version is private and will be removed soon\")\n    def _version(self) -> _Version:\n        return _Version(\n            self._epoch, self._release, self._dev, self._pre, self._post, self._local\n        )\n\n    @_version.setter\n    @_deprecated(\"Version._version is private and will be removed soon\")\n    def _version(self, value: _Version) -> None:\n        self._epoch = value.epoch\n        self._release = value.release\n        self._dev = value.dev\n        self._pre = value.pre\n        self._post = value.post\n        self._local = value.local\n        self._key_cache = None","sourceCodeStart":801,"sourceCodeEnd":837,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/version.py#L801-L837","documentation":"Raised by Version.__setstate__ when restoring (unpickling/copying) a Version object whose serialized state does not match any of the three supported historical layouts: a 6-tuple (packaging 26.2+), a 2-tuple of (None, slot-dict) (packaging 26.0-26.1), or a plain dict with a '_version' NamedTuple (packaging <=25.x). The library supports cross-version migration of its pickle format, but bails out with a TypeError when the state is structurally unrecognizable. This protects callers from silently constructing a Version with garbage fields.","triggerScenarios":"Unpickling a Version instance whose pickle payload was produced by an incompatible/modified packaging version, a hand-built state object, or data corrupted in transit/storage. copy.deepcopy, multiprocessing, or caching layers (pickle, shelve, redis) that round-trip Version objects across processes running different packaging versions trigger __setstate__.","commonSituations":"Upgrading or downgrading pip/packaging in a venv while a cached pickle of a Version object (e.g. from pip's resolver cache, a test fixture, or a user app that pickles parsed versions) survives. Also when a custom __reduce__ or external serializer mangles the Version state.","solutions":["Re-create the Version object from its string form on the consuming side: pickle/serialize the str(version) and re-parse with Version(str_version) instead of pickling the object itself.","Align the packaging/pip version on both the producing and consuming sides so the pickle state format matches (the three supported formats span packaging <=25.x, 26.0-26.1, and 26.2+).","If you control the state object, ensure it is a 6-tuple (epoch, release, pre, post, dev, local) matching __getstate__ before calling __setstate__."],"exampleFix":"// before\nimport pickle\nfrom pip._vendor.packaging.version import Version\nblob = pickle.dumps(Version(\"1.2.3\"))  # sent across packaging versions\nv = pickle.loads(blob)  # may raise \"Cannot restore Version from ...\"\n\n// after\nv = Version(pickle.loads(blob_str))  # serialize the string, re-parse on read","handlingStrategy":"try-catch","validationCode":"import re\nfrom pip._vendor.packaging.version import Version\n\ndef is_restorable_version_state(state):\n    if isinstance(state, tuple) and len(state) == 6:\n        return True\n    if isinstance(state, tuple) and len(state) == 2 and isinstance(state[1], dict):\n        return all(k in state[1] for k in ('_epoch', '_release'))\n    if isinstance(state, dict) and state.get('_version') is not None:\n        return True\n    return False\n\ndef safe_restore(state, fallback_str):\n    try:\n        v = Version.__new__(Version)\n        v.__setstate__(state)\n        return v\n    except TypeError:\n        return Version(fallback_str)","typeGuard":"# No meaningful runtime type guard for opaque pickle state;\n# guard by serializing the *string* form instead of the object.\ndef version_payload(v):\n    return ('version_str', str(v))  # round-trip str, not the object","tryCatchPattern":"try:\n    v = pickle.loads(blob)\nexcept TypeError as e:\n    if 'Cannot restore Version' in str(e):\n        raise ValueError('Incompatible packaging pickle; re-create from string') from e\n    raise","preventionTips":["Serialize str(version) and re-parse with Version() on read instead of pickling the object.","Pin the same packaging/pip version on producers and consumers that round-trip Version objects.","Avoid storing Version objects in long-lived caches that outlive a packaging upgrade."],"tags":["version","pickle","deserialization","packaging","compatibility"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}