{"id":"4bdb8ef21e08b0e8","repo":"pypa/pip","slug":"invalid-licenseref-final-token-r","errorCode":null,"errorMessage":"Invalid licenseref: {final_token!r}","messagePattern":"Invalid licenseref: (.+?)","errorType":"validation","errorClass":"InvalidLicenseExpression","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/licenses/__init__.py","lineNumber":173,"sourceCode":"\n        if normalized_tokens and normalized_tokens[-1] == \"WITH\":\n            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        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                if not license_ref_allowed.match(final_token):\n                    message = f\"Invalid licenseref: {final_token!r}\"\n                    raise InvalidLicenseExpression(message)\n                normalized_tokens.append(license_refs[final_token] + suffix)\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\n    normalized_expression = \" \".join(normalized_tokens)\n\n    return cast(\n        \"NormalizedLicenseExpression\",\n        normalized_expression.replace(\"( \", \"(\").replace(\" )\", \")\"),\n    )\n","sourceCodeStart":155,"sourceCodeEnd":187,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/licenses/__init__.py#L155-L187","documentation":"Raised by `canonicalize_license_expression` when a `LicenseRef-*` token contains characters outside the allowed set `[A-Za-z0-9.-]`. packaging extends SPDX to allow arbitrary LicenseRef identifiers (not just the standard Public-Domain/Proprietary), but still enforces a character whitelist on the part after `LicenseRef-`.","triggerScenarios":"Expressions like `LicenseRef-My Org` (space), `LicenseRef-foo_bar` (underscore not allowed), `LicenseRef-äö` (non-ASCII), or `LicenseRef-a/b` (slash). The regex `^[A-Za-z0-9.-]*$` rejects these.","commonSituations":"Using underscores or spaces in custom license identifiers; Unicode characters in proprietary license names;slashes or colons from file paths accidentally embedded in the ref.","solutions":["Restrict LicenseRef identifiers to letters, digits, dots, and hyphens only","Replace disallowed characters (e.g. `_` → `-`, space → `-`)","Validate with the regex `^[A-Za-z0-9.-]*$` on the part after `LicenseRef-` before canonicalizing"],"exampleFix":"// before\nlicense = \"LicenseRef-My_Custom_License\"\n// after\nlicense = \"LicenseRef-My-Custom-License\"","handlingStrategy":"validation","validationCode":"import re\nLICENSEREF_ALLOWED = re.compile(r'^[A-Za-z0-9.-]*$')\n\ndef validate_licenseref(token: str) -> None:\n    if token.lower().startswith('licenseref-'):\n        suffix = token[len('LicenseRef-'):]\n        if not LICENSEREF_ALLOWED.match(suffix):\n            raise ValueError(f'invalid chars in LicenseRef: {token!r}')","typeGuard":"import re\ndef is_valid_licenseref(token: str) -> bool:\n    suffix = token[len('LicenseRef-'):] if token.lower().startswith('licenseref-') else token\n    return bool(re.match(r'^[A-Za-z0-9.-]*$', suffix))","tryCatchPattern":"from packaging.licenses import canonicalize_license_expression, InvalidLicenseExpression\nimport re\ntry:\n    canonicalize_license_expression(expr)\nexcept InvalidLicenseExpression as e:\n    if 'Invalid licenseref' in str(e):\n        expr = re.sub(r'[^A-Za-z0-9.-]', '-', expr)  # sanitize\n        canonicalize_license_expression(expr)\n    raise","preventionTips":["Restrict LicenseRef suffixes to [A-Za-z0-9.-]","Replace underscores/spaces with hyphens when generating LicenseRef identifiers","Validate identifiers against the regex before adding them to pyproject.toml"],"tags":["packaging","licenses","spdx","pep639","validation"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}