{"record":{"id":"81e9cb33d3016fae","repo":"pypa/pip","slug":"cannot-serialize-marker-value-containing-both-quot","errorCode":null,"errorMessage":"Cannot serialize marker value containing both quote characters","messagePattern":"Cannot serialize marker value containing both quote characters","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/_parser.py","lineNumber":76,"sourceCode":"\n\nclass Variable(Node):\n    __slots__ = ()\n\n    def serialize(self) -> str:\n        return str(self)\n\n\nclass Value(Node):\n    __slots__ = ()\n\n    def serialize(self) -> str:\n        value = str(self)\n        if '\"' not in value:\n            return f'\"{value}\"'\n        if \"'\" not in value:\n            return f\"'{value}'\"\n        raise ValueError(\n            \"Cannot serialize marker value containing both quote characters\"\n        )\n\n\nclass Op(Node):\n    __slots__ = ()\n\n    def serialize(self) -> str:\n        return str(self)\n\n\nMarkerLogical = Literal[\"and\", \"or\"]\nMarkerVar = Union[Variable, Value]\nMarkerItem = tuple[MarkerVar, Op, MarkerVar]\nMarkerAtom = Union[MarkerItem, Sequence[\"MarkerAtom\"]]\nMarkerList = list[Union[\"MarkerList\", MarkerAtom, MarkerLogical]]\n\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/_parser.py#L58-L94","documentation":"Value.serialize() must wrap the marker value string in quotes for PEP 508 compliance. It tries double quotes first; if the string contains a double quote, it falls back to single quotes. If the string contains both quote types, no valid delimiter exists and ValueError is raised. This is a fundamental limitation of PEP 508 marker string syntax.","triggerScenarios":"Serializing a Value node (a parsed marker string literal) whose content contains both single and double quote characters, e.g. a value like He said \"hi\" and left.","commonSituations":"Programmatically constructing marker values from user input or environment data that naturally contains both apostrophes and double quotes. Building markers from arbitrary strings without sanitization.","solutions":["Sanitize the value to remove or escape one quote type before constructing the marker Value","Use only single or double quotes consistently in marker values","Validate marker values before calling serialize()"],"exampleFix":"# before\nfrom packaging._parser import Value\nv = Value('it\\'s \"quoted\"')\nserialized = v.serialize()  # raises ValueError\n\n# after\nraw = 'it\\'s \"quoted\"'.replace('\"', '')  # remove one quote type\nv = Value(raw)\nserialized = v.serialize()  # works","handlingStrategy":"validation","validationCode":"def validate_marker_value(value: str) -> str:\n    if '\"' in value and \"'\" in value:\n        raise ValueError(f\"Marker value cannot contain both quote types: {value!r}\")\n    return value","typeGuard":"def is_serializable_marker_value(value: str) -> bool:\n    return not ('\"' in value and \"'\" in value)","tryCatchPattern":"try:\n    serialized = value_node.serialize()\nexcept ValueError as e:\n    if \"both quote characters\" in str(e):\n        value_node.value = value_node.value.replace(\"'\", \"\")\n        serialized = value_node.serialize()","preventionTips":["Sanitize user input before creating marker values","Avoid embedding both quote types in environment markers","Validate marker values programmatically before serialization"],"tags":["packaging","markers","pep508","serialization","vendored"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}