pypa/pip · error · ValueError
paths must be relative
Error message
paths must be relative
What it means
pyproject_hooks' norm_and_check raises ValueError('paths must be relative') when a backend-path entry in pyproject.toml [build-system] is an absolute path. PEP 517 requires backend-path entries to be relative so the backend is loaded from within the project source tree.
Source
Thrown at src/pip/_vendor/pyproject_hooks/_impl.py:111
This uses :func:`subprocess.check_output` under the hood.
"""
env = os.environ.copy()
if extra_environ:
env.update(extra_environ)
check_output(cmd, cwd=cwd, env=env, stderr=STDOUT)
def norm_and_check(source_tree: str, requested: str) -> str:
"""Normalise and check a backend path.
Ensure that the requested backend path is specified as a relative path,
and resolves to a location under the given source tree.
Return an absolute version of the requested path.
"""
if os.path.isabs(requested):
raise ValueError("paths must be relative")
abs_source = os.path.abspath(source_tree)
abs_requested = os.path.normpath(os.path.join(abs_source, requested))
# We have to use commonprefix for Python 2.7 compatibility. So we
# normalise case to avoid problems because commonprefix is a character
# based comparison :-(
norm_source = os.path.normcase(abs_source)
norm_requested = os.path.normcase(abs_requested)
if os.path.commonprefix([norm_source, norm_requested]) != norm_source:
raise ValueError("paths must be inside source tree")
return abs_requested
class BuildBackendHookCaller:
"""A wrapper to call the build backend hooks for a source directory."""
def __init__(View on GitHub (pinned to d7d0d0a394)
Solutions
- Change the backend-path entry in pyproject.toml to a path relative to the project root (where pyproject.toml lives).
- If a tool is absolutizing the path, pass the source_dir correctly so a relative entry resolves properly.
- Move the backend code under the source tree and reference it relatively.
Example fix
# before [build-system] build-backend = "my_backend" backend-path = ["/home/user/proj/my_backend"] # after [build-system] build-backend = "my_backend" backend-path = ["my_backend"]
Defensive patterns
Strategy: validation
Validate before calling
import os
for p in backend_paths:
if os.path.isabs(p):
raise ValueError(f'backend-path must be relative: {p!r}') Type guard
def is_relative_path(p: str) -> bool:
return isinstance(p, str) and not os.path.isabs(p) Try / catch
from pip._vendor.pyproject_hooks._impl import BuildBackendHookCaller
try:
caller = BuildBackendHookCaller(src, backend, backend_path=paths)
except ValueError:
paths = [os.path.relpath(p, src) for p in paths]
caller = BuildBackendHookCaller(src, backend, backend_path=paths) Prevention
- Keep backend-path entries relative in pyproject.toml.
- Validate paths with os.path.isabs before constructing the hook caller.
When it happens
Trigger: Constructing BuildBackendHookCaller with backend_path containing an absolute path (os.path.isabs(requested) is True), which happens when pyproject.toml lists absolute directories under [build-system] backend-path, e.g. backend-path = ['/abs/repo/backend'].
Common situations: Hand-editing pyproject.toml to point at an absolute backend location; build tools that resolve paths to absolute before passing them; Windows paths like 'C:\\backends\\x' that are inherently absolute.
Related errors
- paths must be inside source tree
- Cannot find module {self.backend_module!r} in {self.backend_
- Error while importing backend
- Cannot import {mod_path!r}
- Some build dependencies for {requirement} conflict with {con
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/1bbf792074655909.json.
Report an issue: GitHub.