{"id":"2887aff69d536d26","repo":"pypa/pip","slug":"cannot-restore-requirement-from-state-r","errorCode":null,"errorMessage":"Cannot restore Requirement from {state!r}","messagePattern":"Cannot restore Requirement from (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/requirements.py","lineNumber":97,"sourceCode":"            yield f\" @ {self.url}\"\n            if self.marker:\n                yield \" \"\n\n        if self.marker:\n            yield f\"; {self.marker}\"\n\n    def __getstate__(self) -> str:\n        # Return the requirement string for compactness and stability.\n        # Re-parsed on load to reconstruct all fields.\n        return str(self)\n\n    def __setstate__(self, state: object) -> None:\n        if isinstance(state, str):\n            # New format (26.2+): just the requirement string.\n            try:\n                tmp = Requirement(state)\n            except InvalidRequirement as exc:\n                raise TypeError(f\"Cannot restore Requirement from {state!r}\") from exc\n            self.name = tmp.name\n            self.url = tmp.url\n            self.extras = tmp.extras\n            self.specifier = tmp.specifier\n            self.marker = tmp.marker\n            return\n        if isinstance(state, dict):\n            # Old format (packaging <= 26.1, no __slots__): plain __dict__.\n            self.__dict__.update(state)\n            return\n        raise TypeError(f\"Cannot restore Requirement from {state!r}\")\n\n    def __str__(self) -> str:\n        return \"\".join(self._iter_parts(self.name))\n\n    def __repr__(self) -> str:\n        return f\"<{self.__class__.__name__}({str(self)!r})>\"\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/requirements.py#L79-L115","documentation":"Raised as TypeError (requirements.py:97) inside Requirement.__setstate__ when unpickling a Requirement whose stored state is the new-format string (packaging >=26.2) but that string no longer parses via Requirement(). The constructor failure (InvalidRequirement) is re-raised as this TypeError so the pickle layer reports an unreadable pickle.","triggerScenarios":"pickle.load() on a pickle produced by packaging >=26.2 where the requirement string has since become invalid (parser regression, manual edit, cross-vendor parser differences). The new __getstate__ returns str(self), so any corruption of that string trips this path.","commonSituations":"Loading a cached pickle (e.g. a resolved requirements cache) after upgrading packaging in a way that tightened the PEP 508 grammar. Cross-process handoff where the producer and consumer disagree on requirement-string validity.","solutions":["Discard the stale pickle/cache and rebuild the Requirement from the original requirement string.","Pin both producer and consumer to the same packaging version.","Catch TypeError around pickle.load and fall back to re-parsing Requirement(str(...)) from a trusted source."],"exampleFix":"# before\nreq = pickle.load(open(\"cache.pkl\", \"rb\"))  # raises TypeError\n\n# after\ntry:\n    req = pickle.load(open(\"cache.pkl\", \"rb\"))\nexcept TypeError:\n    from pip._vendor.packaging.requirements import Requirement\n    req = Requirement(open(\"req.txt\").read().strip())","handlingStrategy":"try-catch","validationCode":"from pip._vendor.packaging.requirements import Requirement, InvalidRequirement\ndef requirement_string_restorable(req_string):\n    try:\n        Requirement(req_string)\n        return True\n    except InvalidRequirement:\n        return False","typeGuard":"null","tryCatchPattern":"import pickle\nfrom pip._vendor.packaging.requirements import Requirement\ntry:\n    obj = pickle.load(open(path, 'rb'))\nexcept TypeError as e:\n    if 'Cannot restore Requirement' in str(e):\n        obj = Requirement(trusted_requirement_string())","preventionTips":["Do not persist Requirement objects as pickles across packaging upgrades; store str(req) instead.","Pin producer and consumer packaging to the same version when exchanging pickles."],"tags":["packaging","pickle","requirements","serialization"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}