pypa/pip · error · InstallationError
is not a valid editable requirement. It should either be a…
Error message
{editable_req} is not a valid editable requirement. It should either be a path to a local project or a VCS URL (beginning with {backends}). What it means
Raised by parse_editable (constructors.py:159) when an editable requirement string parses to a URL that is neither a VCS URL (git+/hg+/svn+/bzr+) nor a file:// path. Editable installs require either a local project path or a VCS checkout URL; anything else is rejected with the list of accepted VCS schemes.
Solutions
- For a local project, give the directory path: 'pip install -e ./path/to/project'.
- For a remote repo, use a VCS scheme: 'pip install -e git+https://github.com/x/y.git'.
- If you only need a non-editable install from a URL, drop the -e flag and use a direct URL/reference.
Example fix
# before pip install -e https://github.com/user/repo # after pip install -e git+https://github.com/user/repo.git # or local pip install -e ./myproject
Defensive patterns
Strategy: validation
Validate before calling
from pip._internal.vcs import vcs
def is_valid_editable_target(line: str) -> bool:
low = line.lower()
if low.startswith('file:'):
return True
import os
if os.path.isdir(line):
return True
return any(low.startswith(s + '+') or low.startswith(s + ':') for s in vcs.all_schemes)
if __name__ == '__main__':
import sys
if not is_valid_editable_target(sys.argv[1]):
print(f'{sys.argv[1]!r} is not a local path or VCS URL'); sys.exit(1) Type guard
from pip._internal.vcs import vcs
import os
def is_editable_compatible(line: str) -> bool:
low = line.lower()
return (low.startswith('file:')
or os.path.isdir(line)
or any(low.startswith(s + '+') or low.startswith(s + ':') for s in vcs.all_schemes)) Try / catch
from subprocess import run, CalledProcessError
try:
run(["pip", "install", "-e", target], check=True)
except CalledProcessError:
# Convert http(s) URL to a VCS URL or use non-editable install.
run(["pip", "install", "-e", "git+" + target], check=True) Prevention
- Use a VCS scheme (git+/hg+/svn+/bzr+) for remote editable installs.
- Use a local directory path for local editable installs.
- Drop -e for plain remote URLs that are not checkouts.
When it happens
Trigger: Passing '-e <something>' where <something> resolves to an http(s) URL, an unsupported scheme, or a non-path string that isn't recognized as file: or a VCS scheme. Checked via link.is_vcs and link.url.startswith('file:').
Common situations: Typing 'pip install -e https://github.com/x/y' instead of 'pip install -e git+https://...'; using an http:// URL for editable install; a path that doesn't exist and isn't converted to file:.
Related errors
- Could not detect requirement name for
- Invalid requirement
- Can't verify hashes for these file:// requirements because…
- Can't verify hashes for these requirements because we don't…
- [dependency-groups] data was invalid in
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/7d1114fff6610257.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/req/constructors.py:159
"""Parses an editable requirement into:
- a requirement name with environment markers
- an URL
- extras
Accepted requirements:
- svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir
- local_path[some_extra]
- Foobar[extra] @ svn+http://blahblah@rev#subdirectory=subdir ; markers
"""
try:
package_name, url, extras = _parse_direct_url_editable(editable_req)
except ValueError:
package_name, url, extras = _parse_pip_syntax_editable(editable_req)
link = Link(url)
if not link.is_vcs and not link.url.startswith("file:"):
backends = ", ".join(vcs.all_schemes)
raise InstallationError(
f"{editable_req} is not a valid editable requirement. "
f"It should either be a path to a local project or a VCS URL "
f"(beginning with {backends})."
)
# The project name can be inferred from local file URIs easily.
if not package_name and not link.url.startswith("file:"):
raise InstallationError(
f"Could not detect requirement name for '{editable_req}', "
"please specify one with your_package_name @ URL"
)
return package_name, url, extras
def check_first_requirement_in_file(filename: str) -> None:
"""Check if file is parsable as a requirements file.
This is heavily based on ``pkg_resources.parse_requirements``, butView on GitHub (pinned to f399c37189)