pypa/pip · error · DirectUrlValidationError
URL scheme must be file:// when dir_info is present
Error message
URL scheme must be file:// when dir_info is present
What it means
When dir_info is present in a direct URL, the source is a local directory. PEP 610 requires the URL scheme to be file://. If the URL has a different scheme (e.g. https://, git+https://), DirectUrlValidationError is raised because a directory source cannot have a remote URL scheme.
Solutions
- If the source is truly a local directory, use a file:// URL (e.g. via pathlib.Path.as_uri())
- If the source is remote, use archive_info or vcs_info instead of dir_info
- Fix the URL scheme to match the info block type
Example fix
# before
data = {
"url": "https://example.com/local/project",
"dir_info": {"editable": True}
}
# after (if truly local)
from pathlib import Path
data = {
"url": Path("/local/project").as_uri(),
"dir_info": {"editable": True}
}
# or if remote, use archive_info:
data = {
"url": "https://example.com/project.tar.gz",
"archive_info": {"hashes": {"sha256": "..."}}
} Defensive patterns
Strategy: validation
Validate before calling
import urllib.parse
def validate_dir_info_url(data: dict) -> None:
if data.get("dir_info") is not None:
scheme = urllib.parse.urlsplit(data["url"]).scheme
if scheme != "file":
raise ValueError(f"dir_info requires file:// URL, got scheme: {scheme!r}") Type guard
import urllib.parse
def is_valid_dir_url(data: dict) -> bool:
if data.get("dir_info") is None:
return True
return urllib.parse.urlsplit(data["url"]).scheme == "file" Try / catch
from packaging.direct_url import DirectUrl, DirectUrlValidationError
try:
du = DirectUrl.from_dict(data)
except DirectUrlValidationError as e:
if "scheme must be file" in str(e):
# convert to file URL or switch info block type
pass Prevention
- Use pathlib.Path.as_uri() to generate correct file:// URLs
- Match info block type to the actual source type
- Validate URL scheme consistency with info blocks
When it happens
Trigger: Calling DirectUrl.from_dict(data) with dir_info present but the url field using a non-file scheme: e.g. {'url': 'https://example.com/path', 'dir_info': {'editable': true}}.
Common situations: Using dir_info when the source is actually a remote archive or VCS repo (wrong info block type). Hand-crafted metadata with a mismatched URL scheme and info block.
Related errors
- File URL must be absolute when dir_info is present
- Exactly one of vcs_info, archive_info, dir_info must be…
- Unexpected type (expected )
- Algorithm used in hash field has different value in hashes…
- Algorithm used in hash field is not present in hashes field
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/1c2c0784d5adde78.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/packaging/direct_url.py:300
direct_url = cls(
url=_get_required(d, str, "url"),
archive_info=_get_object(d, ArchiveInfo, "archive_info"),
vcs_info=_get_object(d, VcsInfo, "vcs_info"),
dir_info=_get_object(d, DirInfo, "dir_info"),
subdirectory=_get(d, str, "subdirectory"),
)
if (
bool(direct_url.vcs_info)
+ bool(direct_url.archive_info)
+ bool(direct_url.dir_info)
) != 1:
raise DirectUrlValidationError(
"Exactly one of vcs_info, archive_info, dir_info must be present"
)
if direct_url.dir_info is not None:
parsed_url = urllib.parse.urlsplit(direct_url.url)
if parsed_url.scheme != "file":
raise DirectUrlValidationError(
"URL scheme must be file:// when dir_info is present",
context="url",
)
if not _file_url_has_absolute_path(parsed_url):
raise DirectUrlValidationError(
"File URL must be absolute when dir_info is present",
context="url",
)
# XXX subdirectory must be relative, can we, should we validate that here?
return direct_url
@classmethod
def from_dict(cls, d: Mapping[str, Any], /) -> Self:
"""Create and validate a DirectUrl instance from a JSON dictionary."""
return cls._from_dict(d)
def to_dict(
self,View on GitHub (pinned to f399c37189)