pypa/pip · error · PylockValidationError
None of vcs, directory, archive must be set if sdist or…
Error message
None of vcs, directory, archive must be set if sdist or wheels are set
What it means
Raised by Package._from_dict in pylock.py:604-607. A package is EITHER a set of built distributions (sdist and/or wheels) OR a single direct-URL source (vcs/directory/archive), never both. If at least one distribution and at least one direct-url source are present together, PylockValidationError is raised.
Solutions
- Split into separate package entries (one for the built distribution, one for the source), or
- Drop the vcs/directory/archive fields so only sdist/wheels remain (or vice-versa).
Example fix
# before
[[packages]]
name = "x"
wheels = [{ name = "x-1.0-py3-none-any.whl", hashes = {...} }]
[packages.directory]
path = "./x"
# after
[[packages]]
name = "x"
wheels = [{ name = "x-1.0-py3-none-any.whl", hashes = {...} }] Defensive patterns
Strategy: validation
Validate before calling
def package_source_consistent(pkg) -> bool:
distributions = bool(pkg.get("sdist")) + len(pkg.get("wheels") or [])
direct = bool(pkg.get("vcs")) + bool(pkg.get("directory")) + bool(pkg.get("archive"))
return not (distributions > 0 and direct > 0)
Try / catch
from packaging.pylock import Pylock, PylockValidationError
try:
Pylock.from_dict(d)
except PylockValidationError as e:
...
Prevention
- Keep each package entry as either built distributions (sdist/wheels) or a single direct URL source, not both.
- Validate at the generator boundary before writing the lock file.
When it happens
Trigger: A [[packages]] entry with both wheels = [...] and directory = {...}; a package with both sdist and vcs; any combination where distributions > 0 and direct_urls > 0.
Common situations: Mixing a built artifact with a source location in one package entry; a merge/union tool combining two package records into one.
Related errors
- Exactly one of vcs, directory, archive must be set if sdist…
- 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/2caffe286d0817d1.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/pylock.py:605
version=_get_as(d, str, Version, "version"),
requires_python=_get_as(d, str, SpecifierSet, "requires-python"),
dependencies=_get_sequence(d, Mapping, "dependencies"), # type: ignore[type-abstract]
marker=_get_as(d, str, Marker, "marker"),
vcs=_get_object(d, PackageVcs, "vcs"),
directory=_get_object(d, PackageDirectory, "directory"),
archive=_get_object(d, PackageArchive, "archive"),
index=_get(d, str, "index"),
sdist=_get_object(d, PackageSdist, "sdist"),
wheels=_get_sequence_of_objects(d, PackageWheel, "wheels"),
attestation_identities=_get_sequence(d, Mapping, "attestation-identities"), # type: ignore[type-abstract]
tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract]
)
distributions = bool(package.sdist) + len(package.wheels or [])
direct_urls = (
bool(package.vcs) + bool(package.directory) + bool(package.archive)
)
if distributions > 0 and direct_urls > 0:
raise PylockValidationError(
"None of vcs, directory, archive must be set if sdist or wheels are set"
)
if distributions == 0 and direct_urls != 1:
raise PylockValidationError(
"Exactly one of vcs, directory, archive must be set "
"if sdist and wheels are not set"
)
for i, wheel in enumerate(package.wheels or []):
try:
(name, version, _, _) = parse_wheel_filename(wheel.filename)
except Exception as e:
raise PylockValidationError(
f"Invalid wheel filename {wheel.filename!r}",
context=f"wheels[{i}]",
) from e
if name != package.name:
raise PylockValidationError(
f"Name in {wheel.filename!r} is not consistent with "View on GitHub (pinned to f399c37189)