pypa/pip · error · InstallationError
Directory entries are not supported in remote pylock.toml
Error message
Directory entries are not supported in remote pylock.toml {pylock_path_or_url!r} What it means
Raised as InstallationError by package_directory_requirement_url (pylock.py:224) when a pylock file loaded from a remote (non-file://) URL contains a package entry of type directory. Directory entries reference local filesystem directories, which only make sense for local lock files. A directory entry in a remote lock file would point to a path on the downloader's machine, which is meaningless or a security risk. The check at line 223 rejects any pylock URL that _is_url and doesn't start with file://.
Solutions
- Convert the directory entry to an archive, sdist, or wheel entry with a downloadable URL.
- Download the pylock.toml to a local path and reference it by path instead of URL.
- Use a file:// URL if the directory is accessible on the local filesystem.
- Regenerate the lock file from a clean checkout and replace local directory references with published artifacts.
Example fix
// before (pylock at https://example.com/lock.toml) [[packages]] name = "mylib" [packages.directory] path = "./mylib" // after # Download lock locally first: $ pip install -r ./lock.toml
Defensive patterns
Strategy: validation
Validate before calling
def is_remote_non_file_url(url: str) -> bool:
"""True if the pylock source is a remote URL (directory entries unsafe)."""
lowered = url.lower()
if lowered.startswith('file://'):
return False
return lowered.startswith('http://') or lowered.startswith('https://')
# Before installing from a remote pylock, scan for directory entries
# and reject or convert them to archive/wheel entries. Type guard
def allows_directory_entries(pylock_source: str) -> bool:
"""True if the pylock source allows directory package entries (local only)."""
return not (
pylock_source.lower().startswith(('http://', 'https://'))
) Prevention
- Do not publish lock files with directory entries to web servers; use local paths.
- Convert local directory dependencies to published archives/wheels before distributing lock files.
- Use file:// URLs for local lock files that need directory entries.
When it happens
Trigger: Loading a pylock.toml from https:// or http:// that contains a [[packages]] entry with a `directory` field (PackageDirectory). The guard at line 223 detects the remote non-file URL and raises.
Common situations: A local lock file (with directory entries) uploaded to a web server or artifact store and then referenced by URL. Lock files generated for monorepo local-development that are accidentally distributed as remote locks.
Related errors
- Absolute paths are not supported in pylock files obtained…
- At least one hash must be provided
- Cannot determine sdist filename
- Cannot determine wheel filename
- Cannot select requirements from pylock file
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/91e228af85733313.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/utils/pylock.py:224
) -> 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})"
)
url += "#subdirectory=" + package_archive.subdirectory
return url
def package_directory_requirement_url(
pylock_path_or_url: str, package_directory: PackageDirectory
) -> str:
if _is_url(pylock_path_or_url) and not pylock_path_or_url.startswith("file://"):
raise InstallationError(
f"Directory entries are not supported in remote pylock.toml "
f"{pylock_path_or_url!r}"
)
url = _package_dist_url(pylock_path_or_url, package_directory.path, None)
assert url.startswith("file://")
if not url.endswith("/"):
url += "/"
if package_directory.subdirectory:
url += package_directory.subdirectory
if not url.endswith("/"):
url += "/"
return url
def package_sdist_requirement_url(
pylock_path_or_url: str, package_sdist: PackageSdist
) -> str:
return _package_dist_url(pylock_path_or_url, package_sdist.path, package_sdist.url)View on GitHub (pinned to f399c37189)