{"id":"be335a8c5ccdb6d9","repo":"pypa/pip","slug":"cannot-restore-tag-from-state-r","errorCode":null,"errorMessage":"Cannot restore Tag from {state!r}","messagePattern":"Cannot restore Tag from (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/tags.py","lineNumber":190,"sourceCode":"        # Cache member _hash is excluded and will be recomputed.\n        return (self._interpreter, self._abi, self._platform)\n\n    def __setstate__(self, state: object) -> None:\n        if isinstance(state, tuple):\n            if len(state) == 3 and all(isinstance(s, str) for s in state):\n                # New format (26.2+): (interpreter, abi, platform)\n                self._interpreter, self._abi, self._platform = state\n                self._hash = hash((self._interpreter, self._abi, self._platform))\n                return\n            if len(state) == 2 and isinstance(state[1], dict):\n                # Old format (packaging <= 26.1, __slots__): (None, {slot: value}).\n                _, slots = state\n                try:\n                    interpreter = slots[\"_interpreter\"]\n                    abi = slots[\"_abi\"]\n                    platform = slots[\"_platform\"]\n                except KeyError:\n                    raise TypeError(f\"Cannot restore Tag from {state!r}\") from None\n                if not all(\n                    isinstance(value, str) for value in (interpreter, abi, platform)\n                ):\n                    raise TypeError(f\"Cannot restore Tag from {state!r}\")\n                self._interpreter = interpreter.lower()\n                self._abi = abi.lower()\n                self._platform = platform.lower()\n                self._hash = hash((self._interpreter, self._abi, self._platform))\n                return\n        raise TypeError(f\"Cannot restore Tag from {state!r}\")\n\n\ndef parse_tag(tag: str, *, validate_order: bool = False) -> frozenset[Tag]:\n    \"\"\"\n    Parses the provided tag (e.g. `py3-none-any`) into a frozenset of\n    :class:`Tag` instances.\n\n    Returning a set is required due to the possibility that the tag is a","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/tags.py#L172-L208","documentation":"Raised as TypeError (tags.py:190) inside Tag.__setstate__ when unpickling the legacy 26.0-26.1 slot-dict format and the slot dict is missing one of _interpreter, _abi, or _platform (KeyError is caught and re-raised as this TypeError). It signals a corrupt or partial pickle in the old format.","triggerScenarios":"pickle.load on a Tag pickled by packaging 26.0-26.1 whose (None, {...}) state dict lacks one of the three slot keys. The except KeyError branch at tags.py:189 converts the lookup failure into this explicit restore error.","commonSituations":"Truncated pickle bytes, a pickle from a Tag subclass that overrode __slots__, or manual mutation of the state dict before unpickling.","solutions":["Discard the corrupt pickle and rebuild the Tag via Tag(interpreter, abi, platform).","Re-serialize Tags on the current packaging version using the new 3-tuple format.","Prefer storing tags as their string form ('py3-none-any') and parsing via parse_tag for cross-version durability."],"exampleFix":"# before: old-format pickle missing a slot\ntag = pickle.load(open(\"t.pkl\", \"rb\"))  # TypeError\n\n# after\nfrom pip._vendor.packaging.tags import Tag\ntag = Tag(\"cp312\", \"cp312\", \"manylinux_2_17_x86_64\")","handlingStrategy":"try-catch","validationCode":"def is_intact_legacy_tag_state(state):\n    if (isinstance(state, tuple) and len(state) == 2 and isinstance(state[1], dict)):\n        slots = state[1]\n        return all(k in slots for k in ('_interpreter', '_abi', '_platform'))\n    return False","typeGuard":"null","tryCatchPattern":"import pickle\nfrom pip._vendor.packaging.tags import Tag\ntry:\n    t = pickle.load(open(path, 'rb'))\nexcept TypeError as e:\n    if 'Cannot restore Tag' in str(e):\n        t = Tag(interp_str, abi_str, platform_str)","preventionTips":["Re-pickle Tags on the current packaging so they use the new 3-tuple format.","Store tags as 'interpreter-abi-platform' strings for durability."],"tags":["packaging","tags","pickle","serialization"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}