{"id":"dfc1bb13b528e477","repo":"pypa/pip","slug":"error-in-string-literal-s","errorCode":null,"errorMessage":"error in string literal: %s","messagePattern":"error in string literal: (.+?)","errorType":"validation","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/distlib/util.py","lineNumber":89,"sourceCode":"            raise SyntaxError('unexpected end of input')\n        else:\n            q = remaining[0]\n            if q not in '\\'\"':\n                raise SyntaxError('invalid expression: %s' % remaining)\n            oq = '\\'\"'.replace(q, '')\n            remaining = remaining[1:]\n            parts = [q]\n            while remaining:\n                # either a string chunk, or oq, or q to terminate\n                if remaining[0] == q:\n                    break\n                elif remaining[0] == oq:\n                    parts.append(oq)\n                    remaining = remaining[1:]\n                else:\n                    m = STRING_CHUNK.match(remaining)\n                    if not m:\n                        raise SyntaxError('error in string literal: %s' % remaining)\n                    parts.append(m.groups()[0])\n                    remaining = remaining[m.end():]\n            else:\n                s = ''.join(parts)\n                raise SyntaxError('unterminated string: %s' % s)\n            parts.append(q)\n            result = ''.join(parts)\n            remaining = remaining[1:].lstrip()  # skip past closing quote\n        return result, remaining\n\n    def marker_expr(remaining):\n        if remaining and remaining[0] == '(':\n            result, remaining = marker(remaining[1:].lstrip())\n            if remaining[0] != ')':\n                raise SyntaxError('unterminated parenthesis: %s' % remaining)\n            remaining = remaining[1:].lstrip()\n        else:\n            lhs, remaining = marker_var(remaining)","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/distlib/util.py#L71-L107","documentation":"Raised inside distlib's PEP 508 marker parser (`parse_marker` -> `marker_var`) while consuming a quoted string literal within an environment marker expression. If the next character is not a valid string chunk per the `STRING_CHUNK` regex (e.g. contains a character not allowed in the chunk class), the parser aborts with `SyntaxError: error in string literal`. This is a vendored copy of distlib used by pip for parsing requirement markers like `; python_version >= '3.8'`.","triggerScenarios":"`parse_marker(marker_string)` is called (transitively when pip parses a requirement with a marker) and a quoted literal in the marker contains a character outside the `STRING_CHUNK` allowed set `[^\\s\\w.{}()*+#:;,/?!~`@$%^&=|<>\\[\\]-]` (e.g. a backslash, an emoji, or an unmatched quote inside the string).","commonSituations":"Typos in requirement markers in `requirements.txt`; copy-pasting markers from documentation that use smart quotes; embedding invalid characters; a stray `\\` or unescaped quote inside the marker string literal.","solutions":["Quote marker string literals with single or double quotes and avoid disallowed characters inside them (notably backslashes and characters outside the chunk class).","Use plain ASCII variable names and values in markers (`python_version`, `sys_platform`, etc.).","Validate the requirement string with `packaging.requirements.Requirement(...)` before passing it to pip."],"exampleFix":"# before\nrequests==2.28.0 ; python_version >= \"3\\.8\"   # backslash inside literal\n\n# after\nrequests==2.28.0 ; python_version >= \"3.8\"","handlingStrategy":"validation","validationCode":"from packaging.markers import Marker, InvalidMarker\n\ndef validate_marker(req_with_marker: str) -> None:\n    # split off the marker after ';'\n    if \";\" in req_with_marker:\n        marker = req_with_marker.split(\";\", 1)[1].strip()\n        try:\n            Marker(marker)\n        except InvalidMarker as e:\n            raise ValueError(f\"Bad marker literal: {e}\") from e","typeGuard":"from packaging.markers import Marker, InvalidMarker\n\ndef is_valid_marker(m: str) -> bool:\n    try:\n        Marker(m)\n        return True\n    except InvalidMarker:\n        return False","tryCatchPattern":"null","preventionTips":["Validate markers with `packaging.markers.Marker(...)` before pip sees them.","Use ASCII, plain quotes (`'...'`), and avoid backslashes in marker literals.","Lint requirements files for non-ASCII smart quotes."],"tags":["distlib","pep508","marker","requirements-parsing"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}