pypa/pip · error · InstallationError
Package URL cannot contain fragments in combination with…
Error message
Package URL {url!r} cannot contain fragments in combination with subdirectory field (in {pylock_path_or_url!r}) What it means
Raised as InstallationError by package_vcs_requirement_url (pylock.py:196) when a VCS package entry in a pylock file already has a # fragment in its constructed URL and also specifies a subdirectory field. URL fragments are used for subdirectory selection, so pip appends #subdirectory=<value> to the VCS URL; if the URL already contains a # (e.g. from a ref or existing fragment), the resulting URL would be ambiguous or malformed. pip refuses rather than produce a broken URL.
Solutions
- Remove the # fragment from the VCS URL in the lock file and rely solely on the subdirectory field.
- If the fragment encodes a ref/branch, move it into the @revision portion of the VCS URL instead of as a # fragment.
- Remove the subdirectory field if the fragment is the intended mechanism for subdirectory selection.
- Regenerate the pylock file with `pip lock` so VCS URLs and subdirectory fields are consistent.
Example fix
// before url = "git+https://repo.git@main#egg=pkg" subdirectory = "subdir" // after url = "git+https://repo.git@main" subdirectory = "subdir"
Defensive patterns
Strategy: validation
Validate before calling
def validate_vcs_url_with_subdir(url: str, subdirectory: str | None) -> bool:
"""True if a VCS URL + subdirectory combination is safe (no conflicting fragment)."""
if subdirectory and '#' in url:
return False # fragment + subdirectory conflict
return True Type guard
def has_fragment_subdir_conflict(url: str, subdirectory: str | None) -> bool:
"""True if the URL has a # fragment AND subdirectory is set (conflict)."""
return bool(subdirectory) and '#' in url Prevention
- Keep VCS ref/branch in the @revision part of the URL, not as a # fragment.
- Use the subdirectory field exclusively for subdir selection — never combine with URL fragments.
- Validate lock files with a schema checker before installing.
When it happens
Trigger: A pylock VCS package whose dist_url (computed from path/url) already contains a '#', and package_vcs.subdirectory is non-empty. The check at line 195 `if '#' in url` triggers the raise at 196.
Common situations: A VCS URL like git+https://repo.git@branch#egg=pkg combined with a subdirectory field in the same lock entry. A pylock file generated by a tool that didn't strip conflicting fragments. Manually editing a lock file and adding both a fragment and a subdirectory.
Related errors
- At least one hash must be provided
- Cannot determine sdist filename
- Cannot determine wheel filename
- Cannot select requirements from pylock file
- Could not detect requirement name for
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/2f6d35d88ef5fb38.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/utils/pylock.py:196
if _is_url(pylock_path_or_url):
raise InstallationError(
f"Absolute paths are not supported in pylock files obtained "
f"from a URL: {path!r} in {pylock_path_or_url!r}"
)
return path_to_url(path)
else:
assert url is not None # guaranteed by packaging.pylock validation
return url
def package_vcs_requirement_url(
pylock_path_or_url: str, package_vcs: PackageVcs
) -> str:
dist_url = _package_dist_url(pylock_path_or_url, package_vcs.path, package_vcs.url)
url = f"{package_vcs.type}+{dist_url}@{package_vcs.commit_id}"
if package_vcs.subdirectory:
if "#" in url:
raise InstallationError(
f"Package URL {url!r} cannot contain fragments in combination "
f"with subdirectory field (in {pylock_path_or_url!r})"
)
url += "#subdirectory=" + package_vcs.subdirectory
return url
def package_archive_requirement_url(
pylock_path_or_url: str, package_archive: PackageArchive
) -> str:
url = _package_dist_url(
pylock_path_or_url, package_archive.path, package_archive.url
)
if package_archive.subdirectory:
if "#" in url:
raise InstallationError(
f"Package URL {url!r} cannot contain fragments in combination "
f"with subdirectory field (in {pylock_path_or_url!r})"View on GitHub (pinned to f399c37189)