{"record":{"id":"99ed8217502d0423","repo":"pypa/pip","slug":"invalid-requirement-s","errorCode":null,"errorMessage":"invalid requirement: %s","messagePattern":"invalid requirement: (.+?)","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/distlib/util.py","lineNumber":253,"sourceCode":"                remaining = remaining[i + 1:].lstrip()\n                # As a special diversion from PEP 508, allow a version number\n                # a.b.c in parentheses as a synonym for ~= a.b.c (because this\n                # is allowed in earlier PEPs)\n                if COMPARE_OP.match(s):\n                    versions, _ = get_versions(s)\n                else:\n                    m = VERSION_IDENTIFIER.match(s)\n                    if not m:\n                        raise SyntaxError('invalid constraint: %s' % s)\n                    v = m.groups()[0]\n                    s = s[m.end():].lstrip()\n                    if s:\n                        raise SyntaxError('invalid constraint: %s' % s)\n                    versions = [('~=', v)]\n\n    if remaining:\n        if remaining[0] != ';':\n            raise SyntaxError('invalid requirement: %s' % remaining)\n        remaining = remaining[1:].lstrip()\n\n        mark_expr, remaining = parse_marker(remaining)\n\n    if remaining and remaining[0] != '#':\n        raise SyntaxError('unexpected trailing data: %s' % remaining)\n\n    if not versions:\n        rs = distname\n    else:\n        rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions]))\n    return Container(name=distname, extras=extras, constraints=versions, marker=mark_expr, url=uri, requirement=rs)\n\n\ndef get_resources_dests(resources_root, rules):\n    \"\"\"Find destinations for resources files\"\"\"\n\n    def get_rel_path(root, path):","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/distlib/util.py#L235-L271","documentation":"Raised as SyntaxError inside parse_requirement when, after consuming the distribution name, extras, URL and version constraints, there is leftover text that does not begin with ';' (the PEP 508 marker separator). It signals that the requirement contains unrecognized trailing structure that is neither a version constraint nor a valid marker clause. The parser expects either an empty remainder or a ';' introducing an environment marker.","triggerScenarios":"parse_requirement('pkg >=1.0 extra_stuff'), parse_requirement('pkg[extra] 1.0'), or any requirement string with a stray token where a comparison operator or ';' is expected. Also produced by requirement strings that accidentally include a second bare version after the first constraint.","commonSituations":"Hand-constructed requirement strings with typos; concatenating name + version without an operator; metadata from non-conformant packages; build tools joining fragments incorrectly.","solutions":["Inspect the reported trailing fragment and remove or reformat it (e.g. add a missing comparison operator).","Use packaging.requirements.Requirement(req_str) to validate the string and surface a clearer PEP 508 diagnostic first.","Rebuild the requirement from a known-good template rather than string concatenation."],"exampleFix":"// before\nparse_requirement('requests 2.25.1 extras')\n// after\nparse_requirement('requests >= 2.25.1')","handlingStrategy":"validation","validationCode":"from packaging.requirements import Requirement\n\ndef safe_parse(req):\n    Requirement(req)  # raises clear PEP 508 error first\n    return parse_requirement(req)","typeGuard":"def looks_like_valid_requirement(s: str) -> bool:\n    try:\n        Requirement(s)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"try:\n    parse_requirement(req)\nexcept SyntaxError as e:\n    if 'invalid requirement' in str(e):\n        log_and_skip(req, e)","preventionTips":["Pre-validate with packaging.requirements.Requirement.","Never build requirements by naive string concatenation."],"tags":["parsing","requirements","pep508","distlib","syntax-error"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}