{"record":{"id":"028e80a25aff2c0e","repo":"pypa/pip","slug":"invalid-project-name-filename-r","errorCode":null,"errorMessage":"Invalid project name: {filename!r}","messagePattern":"Invalid project name: (.+?)","errorType":"validation","errorClass":"InvalidWheelFilename","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/utils.py","lineNumber":271,"sourceCode":"       empty.\n    \"\"\"\n    if not filename.endswith(\".whl\"):\n        raise InvalidWheelFilename(\n            f\"Invalid wheel filename (extension must be '.whl'): {filename!r}\"\n        )\n\n    filename = filename[:-4]\n    dashes = filename.count(\"-\")\n    if dashes not in (4, 5):\n        raise InvalidWheelFilename(\n            f\"Invalid wheel filename (wrong number of parts): {filename!r}\"\n        )\n\n    parts = filename.split(\"-\", dashes - 2)\n    name_part = parts[0]\n    # See PEP 427 for the rules on escaping the project name.\n    if \"__\" in name_part or _wheel_name_regex.match(name_part) is None:\n        raise InvalidWheelFilename(f\"Invalid project name: {filename!r}\")\n    name = canonicalize_name(name_part)\n\n    try:\n        version = Version(parts[1])\n    except InvalidVersion as e:\n        raise InvalidWheelFilename(\n            f\"Invalid wheel filename (invalid version): {filename!r}\"\n        ) from e\n\n    if dashes == 5:\n        build_part = parts[2]\n        build_match = _build_tag_regex.match(build_part)\n        if build_match is None:\n            raise InvalidWheelFilename(\n                f\"Invalid build number: {build_part} in {filename!r}\"\n            )\n        build = cast(\"BuildTag\", (int(build_match.group(1)), build_match.group(2)))\n    else:","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/utils.py#L253-L289","documentation":"Raised by parse_wheel_filename() when the project-name portion of the wheel stem fails validation (utils.py:270). The name must match _wheel_name_regex (^\\w._+$) and must not contain '__' (double underscore is reserved by PEP 427 as the escape for '-'). An empty name also fails this check since the regex requires at least one character.","triggerScenarios":"A wheel filename whose name segment contains '__' (double underscore), is empty, or contains characters outside [\\w._]. For example '-1.0-py3-none-any.whl' (empty name) or 'foo__bar-1.0-py3-none-any.whl' (double underscore).","commonSituations":"A package name with a dash that was incorrectly escaped as '__' instead of '_', or a filename that starts with a version because the name was omitted. Also seen when a malformed wheel is produced by a non-standard build tool.","solutions":["Use a single underscore '_' to separate words in the escaped project name, not '__'.","Ensure the project name is non-empty and contains only [\\w._] characters.","Run the name through canonicalize_name() and re-escape dashes as single underscores."],"exampleFix":"// before\nparse_wheel_filename('foo__bar-1.0-py3-none-any.whl')\n// after\nparse_wheel_filename('foo_bar-1.0-py3-none-any.whl')","handlingStrategy":"validation","validationCode":"import re\n\n_wheel_name_regex = re.compile(r\"^[\\w._]+\\Z\", re.UNICODE)\n\ndef safe_parse_wheel(filename: str):\n    stem = filename[:-4]\n    parts = stem.split(\"-\", 2)\n    name_part = parts[0]\n    if \"__\" in name_part or _wheel_name_regex.match(name_part) is None:\n        raise ValueError(f\"Invalid project name in wheel: {filename!r}\")\n    return parse_wheel_filename(filename)","typeGuard":"def has_valid_wheel_project_name(filename: str) -> bool:\n    if not isinstance(filename, str) or not filename.endswith(\".whl\"):\n        return False\n    name_part = filename[:-4].split(\"-\", 1)[0]\n    return \"__\" not in name_part and bool(re.match(r\"^[\\w._]+$\", name_part))","tryCatchPattern":"from packaging.utils import InvalidWheelFilename\n\ntry:\n    parse_wheel_filename(filename)\nexcept InvalidWheelFilename as e:\n    if \"Invalid project name\" in str(e):\n        logger.error(\"Wheel has invalid project name: %s\", filename)\n    raise","preventionTips":["Use single underscores '_' not '__' for hyphens in escaped project names","Ensure the project name segment is non-empty","Validate the name segment against [\\w._]+ before parsing"],"tags":["wheel","filename","project-name","packaging","pep427"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}