{"record":{"id":"363e01d82b1d7ad3","repo":"pypa/pip","slug":"invalid-licenseref-token-r","errorCode":null,"errorMessage":"Invalid licenseref: {token!r}","messagePattern":"Invalid licenseref: (.+?)","errorType":"validation","errorClass":"InvalidLicenseExpression","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/licenses/__init__.py","lineNumber":184,"sourceCode":"            if token not in EXCEPTIONS:\n                message = f\"Unknown license exception: {token!r}\"\n                raise InvalidLicenseExpression(message)\n\n            normalized_tokens.append(EXCEPTIONS[token][\"id\"])\n            last_license_start = False\n        else:\n            if token.endswith(\"+\"):\n                final_token = token[:-1]\n                suffix = \"+\"\n            else:\n                final_token = token\n                suffix = \"\"\n\n            if final_token.startswith(\"licenseref-\"):\n                license_ref_id = final_token[len(\"licenseref-\") :]\n                if suffix or not license_ref_allowed.match(license_ref_id):\n                    message = f\"Invalid licenseref: {token!r}\"\n                    raise InvalidLicenseExpression(message)\n                normalized_tokens.append(license_refs[final_token])\n            else:\n                if final_token not in LICENSES:\n                    message = f\"Unknown license: {final_token!r}\"\n                    raise InvalidLicenseExpression(message)\n                normalized_tokens.append(LICENSES[final_token][\"id\"] + suffix)\n            last_license_start = True\n\n    normalized_expression = \" \".join(normalized_tokens)\n\n    return cast(\n        \"NormalizedLicenseExpression\",\n        normalized_expression.replace(\"( \", \"(\").replace(\" )\", \")\"),\n    )\n","sourceCodeStart":166,"sourceCodeEnd":199,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/licenses/__init__.py#L166-L199","documentation":"Raised by canonicalize_license_expression (licenses/__init__.py:182-184) for a LicenseRef-* token whose suffix (after 'LicenseRef-') fails the regex ^[A-Za-z0-9.-]+$ (license_ref_allowed) or which carries a '+' OR-later suffix. Custom LicenseRef identifiers are allowed beyond the SPDX built-ins, but they must be alphanumeric with dots/hyphens only and cannot be versioned with '+'.","triggerScenarios":"Passing 'LicenseRef-' (empty suffix), 'LicenseRef-My_License' (underscore), 'LicenseRef-foo/bar' (slash), 'LicenseRef-foo bar' (space), or 'LicenseRef-Custom+' (the '+' suffix is rejected for refs).","commonSituations":"Reusing Python-style identifiers (underscores) in a custom license ref; appending '+' thinking OR-later applies to custom licenses; paths/slashes leaking into the ref.","solutions":["Use only [A-Za-z0-9.-] after 'LicenseRef-', replacing underscores with hyphens.","Remove any trailing '+' from a LicenseRef token."],"exampleFix":"# before\ncanonicalize_license_expression('LicenseRef-My_License+')\n# after\ncanonicalize_license_expression('LicenseRef-My-License')","handlingStrategy":"validation","validationCode":"import re\n\n_LICENSE_REF = re.compile(r\"^[A-Za-z0-9.-]+$\")\n\ndef valid_license_ref(token: str) -> bool:\n    t = token.lower()\n    if not t.startswith(\"licenseref-\"):\n        return True  # not a ref, not our concern here\n    if t.endswith(\"+\"):\n        return False\n    suffix = t[len(\"licenseref-\"):]\n    return bool(_LICENSE_REF.match(suffix))\n","typeGuard":null,"tryCatchPattern":"from packaging.licenses import canonicalize_license_expression, InvalidLicenseExpression\n\ntry:\n    canonicalize_license_expression(expr)\nexcept InvalidLicenseExpression:\n    ...\n","preventionTips":["For custom license refs use only letters, digits, dots and hyphens.","Never append '+' to a LicenseRef token."],"tags":["spdx","license","validation","packaging"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}