pypa/pip · error · ValueError
path '%s' cannot end with '/'
Error message
path '%s' cannot end with '/'
What it means
Raised by convert_path() on non-Unix-like systems when the pathname ends with '/'. A trailing separator would collapse to an empty final segment after splitting on '/', which is ambiguous for native path joining, so a ValueError is raised. Like the absolute-path check, it only triggers when os.sep != '/'.
Source
Thrown at src/pip/_vendor/distlib/util.py:476
def convert_path(pathname):
"""Return 'pathname' as a name that will work on the native filesystem.
The path is split on '/' and put back together again using the current
directory separator. Needed because filenames in the setup script are
always supplied in Unix style, and have to be converted to the local
convention before we can actually use them in the filesystem. Raises
ValueError on non-Unix-ish systems if 'pathname' either starts or
ends with a slash.
"""
if os.sep == '/':
return pathname
if not pathname:
return pathname
if pathname[0] == '/':
raise ValueError("path '%s' cannot be absolute" % pathname)
if pathname[-1] == '/':
raise ValueError("path '%s' cannot end with '/'" % pathname)
paths = pathname.split('/')
while os.curdir in paths:
paths.remove(os.curdir)
if not paths:
return os.curdir
return os.path.join(*paths)
class FileOperator(object):
def __init__(self, dry_run=False):
self.dry_run = dry_run
self.ensured = set()
self._init_record()
def _init_record(self):
self.record = FalseView on GitHub (pinned to d7d0d0a394)
Solutions
- Strip the trailing '/': convert_path('src/mypkg'.rstrip('/')).
- Build paths with os.path.join and strip the separator before passing to convert_path.
- Validate with 'if pathname.endswith("/"): pathname = pathname[:-1]'.
Example fix
// before
convert_path('src/mypkg/') # on Windows
// after
convert_path('src/mypkg') Defensive patterns
Strategy: validation
Validate before calling
import os
def safe_convert_path(p):
if os.sep != '/' and p.endswith('/'):
p = p.rstrip('/')
from distlib.util import convert_path
return convert_path(p) Try / catch
from distlib.util import convert_path
try:
native = convert_path(p)
except ValueError as e:
if 'cannot end with' in str(e):
native = convert_path(p.rstrip('/'))
else:
raise Prevention
- Normalize paths with p.rstrip('/') before convert_path().
- Build paths with os.path.join rather than string concatenation with '/'.
- Run packaging tests on Windows to catch platform-specific path issues.
When it happens
Trigger: Calling convert_path('src/mypkg/') on Windows, or setup() receiving a directory-style path with a trailing slash on Windows.
Common situations: Path joining code that appends '/' unconditionally, or copy-pasted directory paths that retain their trailing separator.
Related errors
- path '%s' cannot be absolute
- Target path exists but is not a directory, will not continue
- {req_name} does not appear to be a Python project: neither '
- Directory {name!r} is not installable. Neither 'setup.py' no
- file '%r' does not exist
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/ebe56e225dba2514.json.
Report an issue: GitHub.