astral-sh/ruff · error · RuffNotFound
Could not find the ruff binary in any of the following locat
Error message
Could not find the ruff binary in any of the following locations:
{locations}
What it means
The ruff PyPI package is a thin Python wrapper around a prebuilt Rust executable. find_ruff_bin() in python/ruff/_find_ruff.py probes a fixed list of locations (the current Python's scripts dir, the base-prefix scripts dir, the bin directory above the site-packages/ruff package for --prefix and `uv run --with` installs, the bin dir adjacent to the package for pip install --target, and the user scheme scripts dir such as ~/.local/bin) for ruff(.exe). RuffNotFound is raised only when every candidate directory has been checked and none contains the binary; the message lists each location that was actually searched.
Source
Thrown at python/ruff/_find_ruff.py:53
# with module path `<target>/ruff`
_join(_matching_parents(_module_path(), "ruff"), "bin"),
# The user scheme scripts directory, e.g., `~/.local/bin`
sysconfig.get_path("scripts", scheme=_user_scheme()),
]
seen = []
for target in targets:
if not target:
continue
if target in seen:
continue
seen.append(target)
path = os.path.join(target, ruff_exe)
if os.path.isfile(path):
return path
locations = "\n".join(f" - {target}" for target in seen)
raise RuffNotFound(
f"Could not find the ruff binary in any of the following locations:\n{locations}\n"
)
def _module_path() -> str | None:
path = os.path.dirname(__file__)
return path
def _matching_parents(path: str | None, match: str) -> str | None:
"""
Return the parent directory of `path` after trimming a `match` from the end.
The match is expected to contain `/` as a path separator, while the `path`
is expected to use the platform's path separator (e.g., `os.sep`). The path
components are compared case-insensitively and a `*` wildcard can be used
in the `match`.
"""
from fnmatch import fnmatchView on GitHub (pinned to d1087a4b9e)
Solutions
- Force-reinstall from a prebuilt wheel: pip install --force-reinstall --only-binary :all: ruff (or uv pip install --reinstall ruff).
- Verify a wheel exists for your platform on PyPI; if not, switch base image/platform (e.g. manylinux instead of musl) or build the binary with cargo and put it on PATH.
- If the binary exists elsewhere (vendored or moved), copy ruff(.exe) into one of the directories listed in the error message (e.g. the scripts dir or the bin directory next to the package).
- Bypass the wrapper entirely and run the binary via uvx ruff or the standalone installer.
Example fix
# before: source install without a platform wheel pip install ruff --no-binary ruff python -m ruff --version # RuffNotFound: binary missing from every searched location # after: install the platform wheel that bundles the executable pip install --only-binary :all: --force-reinstall ruff python -m ruff --version # ruff x.y.z
Defensive patterns
Strategy: try-catch
Validate before calling
import sysconfig
from pathlib import Path
def ruff_binary_available() -> bool:
try:
import ruff # noqa: F401
except ImportError:
return False
exe = 'ruff' + (sysconfig.get_config_var('EXE') or '')
pkg_dir = Path(ruff.__file__).parent
candidates = [
sysconfig.get_path('scripts'),
sysconfig.get_path('scripts', vars={'base': sys.base_prefix}),
str(pkg_dir.parent / 'bin'),
]
return any(p and Path(p, exe).is_file() for p in candidates) Try / catch
from ruff._find_ruff import RuffNotFound, find_ruff_bin
import shutil
try:
ruff_bin = find_ruff_bin()
except RuffNotFound:
ruff_bin = shutil.which('ruff') # fall back to a binary on PATH
if ruff_bin is None:
raise Prevention
- Pin ruff installs to prebuilt platform wheels (--only-binary :all:).
- Add a post-install smoke test in Docker/CI: python -m ruff --version.
- When vendoring with pip install --target, also copy the adjacent bin/ directory.
- Prefer uvx ruff or the standalone installer where wheel installs are unreliable.
When it happens
Trigger: Calling find_ruff_bin() (directly, or indirectly via `python -m ruff` or the generated Python API) when the ruff executable is absent from all probed directories: an sdist/source install that never shipped a binary, a wheel for a platform without prebuilt artifacts, a container image whose cleanup step deleted compiled files, or a pip install --target/--prefix layout where the sibling bin directory was not created.
Common situations: Docker multi-stage builds that strip site-packages; musl-based or exotic-architecture images where pip builds from source without placing the binary; mixing conda and pip environments; vendoring the ruff package without its bin directory; CI caching a broken wheel.
Related errors
- Brackets are not balanced for type {rust_type_str}
- Expected a ty `File`, found a ruff `SourceFile`
- Expected Stmt::ImportFrom
- Expected ScopeKind::Function | ScopeKind::Lambda
- Expected Stmt::Import | Stmt::ImportFrom
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/295545d13a89c81c.
Report an issue: GitHub.