{"id":"5e9b4171bf9484c3","repo":"pypa/pip","slug":"cannot-restore-marker-from-state-r","errorCode":null,"errorMessage":"Cannot restore Marker from {state!r}","messagePattern":"Cannot restore Marker from (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/markers.py","lineNumber":405,"sourceCode":"\n    def __eq__(self, other: object) -> bool:\n        if not isinstance(other, Marker):\n            return NotImplemented\n\n        return str(self) == str(other)\n\n    def __getstate__(self) -> str:\n        # Return the marker expression string for compactness and stability.\n        # Internal Node objects are excluded; the string is re-parsed on load.\n        return str(self)\n\n    def __setstate__(self, state: object) -> None:\n        if isinstance(state, str):\n            # New format (26.2+): just the marker expression string.\n            try:\n                self._markers = _normalize_extra_values(_parse_marker(state))\n            except ParserSyntaxError as exc:\n                raise TypeError(f\"Cannot restore Marker from {state!r}\") from exc\n            return\n        if isinstance(state, dict) and \"_markers\" in state:\n            # Old format (packaging <= 26.1, no __slots__): plain __dict__.\n            markers = state[\"_markers\"]\n            if isinstance(markers, list):\n                self._markers = markers\n                return\n        if isinstance(state, tuple) and len(state) == 2:\n            # Old format (packaging <= 26.1, __slots__): (None, {slot: value}).\n            _, slot_dict = state\n            if isinstance(slot_dict, dict) and \"_markers\" in slot_dict:\n                markers = slot_dict[\"_markers\"]\n                if isinstance(markers, list):\n                    self._markers = markers\n                    return\n        raise TypeError(f\"Cannot restore Marker from {state!r}\")\n\n    def __and__(self, other: Marker) -> Marker:","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/markers.py#L387-L423","documentation":"Raised as TypeError from Marker.__setstate__ when unpickling/copying a Marker whose pickled state is the new (packaging 26.2+) string format, but that string cannot be re-parsed by _parse_marker (raises ParserSyntaxError). The string was supposed to be a valid PEP 508 marker expression but is malformed when restored.","triggerScenarios":"Unpickling a Marker object whose serialized expression string got corrupted (e.g. truncated in a cache, mutated in a database). Using copy.deepcopy on a Marker whose __getstate__ returned a non-expression string subclass. Loading a pickle produced by a buggy custom __reduce__.","commonSituations":"Cross-process caches (multiprocessing, redis) storing pickled Marker objects; rolling a cache forward/backward across packaging versions; test fixtures with hand-edited pickle bytes.","solutions":["Regenerate the Marker from its source string with Marker(expr) instead of unpickling a stale object.","If caching, store the marker expression string and reconstruct Marker(...) on load rather than pickling the object.","Catch TypeError around pickle.loads / copy operations and rebuild the Marker from the original expression.","Validate the cached string with Marker(str) before persisting, so corrupt data is never written."],"exampleFix":"# before\nimport pickle\nm = pickle.loads(cached_bytes)\n# after\nexpr = load_expression_string_from_cache()\nm = Marker(expr)","handlingStrategy":"try-catch","validationCode":"from packaging.markers import Marker\nfrom packaging.markers import ParserSyntaxError\n\ndef validate_marker_string(s: str) -> bool:\n    try:\n        Marker(s)\n        return True\n    except ParserSyntaxError:\n        return False","typeGuard":null,"tryCatchPattern":"import pickle\ntry:\n    m = pickle.loads(data)\nexcept TypeError as e:\n    if 'Cannot restore Marker' in str(e):\n        m = Marker(stored_expr_str)\n    else:\n        raise","preventionTips":["Cache the marker expression string, not the Marker object.","Validate expression strings with Marker(s) before persisting.","Pin packaging versions across processes sharing pickles.","Catch TypeError around unpickle to rebuild from the source string."],"tags":["markers","pickle","serialization","caching"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}