{"id":"2f6d35d88ef5fb38","repo":"pypa/pip","slug":"package-url-url-r-cannot-contain-fragments-in-co","errorCode":null,"errorMessage":"Package URL {url!r} cannot contain fragments in combination with subdirectory field (in {pylock_path_or_url!r})","messagePattern":"Package URL (.+?) cannot contain fragments in combination with subdirectory field \\(in (.+?)\\)","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/utils/pylock.py","lineNumber":196,"sourceCode":"            if _is_url(pylock_path_or_url):\n                raise InstallationError(\n                    f\"Absolute paths are not supported in pylock files obtained \"\n                    f\"from a URL: {path!r} in {pylock_path_or_url!r}\"\n                )\n            return path_to_url(path)\n    else:\n        assert url is not None  # guaranteed by packaging.pylock validation\n        return url\n\n\ndef package_vcs_requirement_url(\n    pylock_path_or_url: str, package_vcs: PackageVcs\n) -> str:\n    dist_url = _package_dist_url(pylock_path_or_url, package_vcs.path, package_vcs.url)\n    url = f\"{package_vcs.type}+{dist_url}@{package_vcs.commit_id}\"\n    if package_vcs.subdirectory:\n        if \"#\" in url:\n            raise InstallationError(\n                f\"Package URL {url!r} cannot contain fragments in combination \"\n                f\"with subdirectory field (in {pylock_path_or_url!r})\"\n            )\n        url += \"#subdirectory=\" + package_vcs.subdirectory\n    return url\n\n\ndef package_archive_requirement_url(\n    pylock_path_or_url: str, package_archive: PackageArchive\n) -> str:\n    url = _package_dist_url(\n        pylock_path_or_url, package_archive.path, package_archive.url\n    )\n    if package_archive.subdirectory:\n        if \"#\" in url:\n            raise InstallationError(\n                f\"Package URL {url!r} cannot contain fragments in combination \"\n                f\"with subdirectory field (in {pylock_path_or_url!r})\"","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/utils/pylock.py#L178-L214","documentation":"InstallationError from package_vcs_requirement_url when a VCS package entry in pylock.toml has both a subdirectory field and a URL that already contains a '#' fragment. pip builds the VCS URL as vcs+url@commit and appends '#subdirectory=...'; a pre-existing fragment would make the URL ambiguous/invalid, so it refuses.","triggerScenarios":"package_vcs.subdirectory is set and the constructed `url` (vcs+dist_url@commit_id) already contains '#'. E.g. a VCS url field ending in '#egg=x' or '#subdirectory=pkg' combined with a subdirectory field on the same entry.","commonSituations":"Migrating an older requirements-style VCS URL (with #egg= or #subdirectory= fragments) into a pylock.toml but also filling the first-class subdirectory field; tooling that emits both redundantly.","solutions":["Remove the '#...' fragment from the VCS url field; express the subdirectory only via the subdirectory field.","Drop the subdirectory field if you intend to keep the fragment (not recommended — prefer the field).","Regenerate the lock with a current tool that emits only the first-class fields."],"exampleFix":"# before\n[[packages.vcs]]\ntype = \"git\"\nurl  = \"https://github.com/o/r.git#subdirectory=pkg\"\nsubdirectory = \"pkg\"\n\n# after\n[[packages.vcs]]\ntype = \"git\"\nurl  = \"https://github.com/o/r.git\"\nsubdirectory = \"pkg\"","handlingStrategy":"validation","validationCode":"def pylock_vcs_entry_is_clean(url, subdirectory):\n    return not (subdirectory and '#' in url)\n# assert before writing/serving a pylock.toml with a VCS entry","typeGuard":null,"tryCatchPattern":"try:\n    pip_install('-r', lock_path)\nexcept InstallationError as e:\n    if 'cannot contain fragments in combination with subdirectory' in str(e):\n        strip_fragment_from_vcs_urls(lock_path)\n        pip_install('-r', lock_path)\n    else:\n        raise","preventionTips":["Express subdirectory via its dedicated field, never via a URL fragment.","Don't migrate old `#egg=`/`#subdirectory=` VCS URLs verbatim into pylock.","Regenerate locks with a current tool that emits first-class fields."],"tags":["pip","pylock","vcs","url","fragment","lockfile"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}