nvbn/thefuck · error · ValueError
Path separators not allowed in script names
Error message
Path separators not allowed in script names
What it means
This ValueError is raised by fastentrypoints, a package that monkey-patches setuptools' easy_install.ScriptWriter.get_args to generate fast, importlib-based console scripts instead of pkg_resources-based ones. During wheel/build processing it iterates over every entry point in the 'console_scripts' and 'gui_scripts' groups and rejects any whose name contains a forward or back slash. The check exists because a script name with a path separator would cause the generated executable wrapper to be written into unintended directories (or escape the build output tree).
Source
Thrown at fastentrypoints.py:68
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit({2}())'''
@classmethod
def get_args(cls, dist, header=None):
"""
Yield write_script() argument tuples for a distribution's
console_scripts and gui_scripts entry points.
"""
if header is None:
header = cls.get_header()
spec = str(dist.as_requirement())
for type_ in 'console', 'gui':
group = type_ + '_scripts'
for name, ep in dist.get_entry_map(group).items():
# ensure_safe_name
if re.search(r'[\\/]', name):
raise ValueError("Path separators not allowed in script names")
script_text = TEMPLATE.format(
ep.module_name, ep.attrs[0], '.'.join(ep.attrs),
spec, group, name)
args = cls._get_script_args(type_, name, header, script_text)
for res in args:
yield res
easy_install.ScriptWriter.get_args = get_args
def main():
import os
import re
import shutil
import sys
dests = sys.argv[1:] or ['.']
filename = re.sub(r'\.pyc$', '.py', __file__)View on GitHub (pinned to c7e7e1d884)
Solutions
- Inspect your project's entry_points declaration (setup.py, setup.cfg [options.entry_points], or pyproject.toml [project.scripts]) and remove any '/' or '\\' from the script name, e.g. change 'bin/tool = mymod:main' to 'tool = mymod:main'.
- If you intend the script to live in a subdirectory of the environment's bin/, note that entry-point names must be plain command names; pick a unique flat name instead (e.g. 'myproject-tool').
- Verify the entry_points string is well formed (correct '=' between name and target, one entry per line in setup.cfg) so the name field is not accidentally picking up a path fragment.
- If the offending name comes from a third-party dependency being built from source, report it upstream; as a local workaround you can uninstall/omit fastentrypoints so stock setuptools ScriptWriter is used (which sanitizes differently) while you patch the metadata.
Example fix
# before (setup.py)
entry_points={
'console_scripts': [
'bin/mytool = myproject.cli:main',
],
}
# after
entry_points={
'console_scripts': [
'mytool = myproject.cli:main',
],
} Defensive patterns
Strategy: validation
Validate before calling
# In setup.py, before declaring entry points, validate every script name:
import re
ENTRY_POINTS = {
'console_scripts': [
'bin/mytool = myproject.cli:main', # would fail
],
}
for group, entries in ENTRY_POINTS.items():
for entry in entries:
name = entry.split('=', 1)[0].strip()
if re.search(r'[\\/]', name):
raise SystemExit(
f"Invalid entry point name {name!r} in {group}: "
"path separators are not allowed (fastentrypoints)") Type guard
# Python: assert entry-point names are flat command names before build
import re
def is_safe_script_name(name: str) -> bool:
"""True if name is a valid console_scripts name for fastentrypoints."""
return bool(name) and not re.search(r'[\\/]', name) and '=' not in name
assert all(is_safe_script_name(e.split('=')[0].strip())
for e in CONSOLE_SCRIPT_ENTRIES) Try / catch
# If you drive builds programmatically, catch and surface the real entry point:
from setuptools.command.easy_install import easy_install
try:
# build/install path that goes through ScriptWriter.get_args
run_setup_command('bdist_wheel')
except ValueError as e:
if 'Path separators not allowed' in str(e):
raise SystemExit('Fix entry_points: script names must not contain / or \\') from e
raise Prevention
- Treat entry-point names as command names, not file paths — pick a single flat token like 'mytool'.
- Add a CI lint step that greps setup.py/setup.cfg/pyproject.toml [project.scripts] sections for '='-LHS values containing '/' or '\\'.
- Test `pip install .` or `python -m build` in CI so bad entry points fail the build before release.
- Prefer pyproject.toml [project.scripts], where tooling and schema checks make stray path characters easier to spot.
When it happens
Trigger: Calling setup.py / setuptools build machinery (e.g. `python setup.py install`, bdist_wheel, or pip installing a project) that has imported fastentrypoints, when the project's setup() declares entry_points like {'console_scripts': ['bin/tool = mymod:main']} or {'gui_scripts': ['sub/dir/app = mymod:main']}. The regex r'[\\/]' matches the slash in the entry-point NAME (the part before '='), triggering the raise at fastentrypoints.py:68.
Common situations: Typos in setup.py/setup.cfg/pyproject.toml entry_points where a path-like name is written instead of a plain command name; migrating a package whose original scripts lived in a subdirectory and copying that layout into the entry-point name; name fields containing Windows-style backslashes; occasionally a corrupted or mis-parsed entry_points string where '=' or newlines are misplaced so the wrong token is treated as the name.
AI-assisted analysis of nvbn/thefuck@c7e7e1d884 (2026-08-14).
Data as JSON: /api/errors/460c42fe909f5fb6.
Report an issue: GitHub.