pypa/pip · error · InstallationError
Error reading pylock file
Error message
Error reading pylock file {pylock_path_or_url!r}: {exc} What it means
Raised as InstallationError by select_from_pylock_path_or_url (pylock.py:281) when the pylock file content cannot be fetched or read. This wraps any non-DiagnosticPipError exception from _get_pylock_path_or_url_content, which handles HTTP fetches (session.get), file:// reads, and local file reads via Path.read_text. The original exception is chained via `from exc`. Common underlying causes: network errors, HTTP 404/403, file not found, permission denied.
Solutions
- Verify the pylock URL/path is correct and accessible (open it in a browser or check with curl).
- For HTTP sources, ensure authentication and network access: set PIP_INDEX_URL, credentials, or proxy env vars as needed.
- For local paths, verify the file exists and is readable (`ls -la <path>`).
- Re-download or regenerate the pylock file if it was lost or corrupted.
Example fix
// before pip install -r https://broken.example.com/missing.toml // after pip install -r https://correct.example.com/pylock.toml
Defensive patterns
Strategy: try-catch
Validate before calling
from urllib.parse import urlsplit
from pathlib import Path
def pylock_source_readable(path_or_url: str) -> bool:
"""Quick pre-check that a pylock source can be read."""
scheme = urlsplit(path_or_url).scheme
if scheme in ('http', 'https', 'file'):
import urllib.request
try:
urllib.request.urlopen(path_or_url, timeout=5)
return True
except Exception:
return False
return Path(path_or_url).is_file() Try / catch
from pip._internal.exceptions import InstallationError
try:
from pip._internal.utils.pylock import select_from_pylock_path_or_url
# select_from_pylock_path_or_url(path_or_url, session)
except InstallationError as e:
if 'Error reading pylock file' in str(e):
# handle I/O / network failure: retry, fix URL, or fall back
pass Prevention
- Verify URLs resolve before referencing them in install commands (curl -I).
- Cache critical lock files locally to avoid network dependencies.
- Set timeouts and retry logic in CI for remote lock file downloads.
When it happens
Trigger: Calling select_from_pylock_path_or_url with a path_or_url that cannot be read: a dead HTTP link (lines 259-260 raise_for_status), a file:// URL to a missing file, or a local path that doesn't exist (Path.read_text at line 264). The except at line 280 catches it and re-raises as InstallationError.
Common situations: Typo in the pylock URL or path. The lock file was deleted or moved. Network connectivity issues or proxy/firewall blocking the request. HTTP authentication required but not provided. Permission denied on a local file.
Related errors
- Absolute paths are not supported in pylock files obtained…
- Could not open file
- Path in pylock file obtained from a URL resolves outside…
- At least one hash must be provided
- Cannot determine sdist filename
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/0f3d8d6ff4b700fd.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/utils/pylock.py:281
# Assume this is a bare path.
return Path(path_or_url).read_text(encoding="utf-8")
def select_from_pylock_path_or_url(
pylock_path_or_url: str,
session: PipSession,
) -> Iterator[
tuple[
Package,
PackageVcs | PackageDirectory | PackageArchive | PackageWheel | PackageSdist,
]
]:
try:
pylock_content = _get_pylock_path_or_url_content(pylock_path_or_url, session)
except DiagnosticPipError:
raise
except Exception as exc:
raise InstallationError(
f"Error reading pylock file {pylock_path_or_url!r}: {exc}"
) from exc
try:
lock = Pylock.from_dict(tomllib.loads(pylock_content))
except Exception as exc:
raise InstallationError(
f"Invalid pylock file {pylock_path_or_url!r}: {exc}"
) from exc
try:
# TODO: for completeness, pylock.select should support preferring sdist
# over wheels to support --no-binary
yield from lock.select()
except Exception as exc:
raise InstallationError(
f"Cannot select requirements from pylock file {pylock_path_or_url!r}: {exc}"
) from excView on GitHub (pinned to f399c37189)