{"record":{"id":"185af9d958c50650","repo":"astral-sh/uv","slug":"uv-bin-name-was-not-properly-installed","errorCode":null,"errorMessage":"{uv_bin_name} was not properly installed","messagePattern":"(.+?) was not properly installed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crates/uv-build/python/uv_build/__init__.py","lineNumber":51,"sourceCode":"    if config_settings:\n        print(\"Warning: Config settings are not supported\", file=sys.stderr)\n\n\ndef call(\n    args: \"Sequence[str]\", config_settings: \"Mapping[Any, Any] | None\" = None\n) -> str:\n    \"\"\"Invoke a uv subprocess and return the filename from stdout.\"\"\"\n    import shutil\n    import subprocess\n    import sys\n\n    warn_config_settings(config_settings)\n\n    uv_bin_name = \"uv\" if USE_UV_EXECUTABLE else \"uv-build\"\n    # Unlike `find_uv_bin`, this mechanism must work according to PEP 517\n    uv_bin = shutil.which(uv_bin_name)\n    if uv_bin is None:\n        raise RuntimeError(f\"{uv_bin_name} was not properly installed\")\n    build_backend_args = [\"build-backend\"] if USE_UV_EXECUTABLE else []\n    # Forward stderr, capture stdout for the filename\n    result = subprocess.run(\n        [uv_bin, *build_backend_args, *args], stdout=subprocess.PIPE, check=False\n    )\n    if result.returncode != 0:\n        sys.exit(result.returncode)\n    # If there was extra stdout, forward it (there should not be extra stdout)\n    stdout = result.stdout.decode(\"utf-8\").strip().splitlines(keepends=True)\n    sys.stdout.writelines(stdout[:-1])\n    # Fail explicitly instead of an irrelevant stacktrace\n    if not stdout:\n        print(\n            f\"{uv_bin_name} subprocess did not return a filename on stdout\",\n            file=sys.stderr,\n        )\n        sys.exit(1)\n    return stdout[-1].strip()","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/astral-sh/uv/blob/f1a42680ff5272232d65748acf338b19778dde24/crates/uv-build/python/uv_build/__init__.py#L33-L69","documentation":"The `uv_build` PEP 517/660 backend is a thin Python shim: every hook (build_sdist, build_wheel, build_editable, ...) calls `call()`, which shells out to the `uv-build` executable (or `uv build-backend` when the distro sets USE_UV_EXECUTABLE=True). PEP 517 frontends run hooks in an isolated subprocess, so the shim cannot use `find_uv_bin`; it relies on `shutil.which(uv_bin_name)`. If that returns None the shim raises RuntimeError to fail fast instead of producing a confusing FileNotFoundError about a missing command.","triggerScenarios":"Any build of a project with `[build-system] build-backend = \"uv_build\"` where `shutil.which(\"uv-build\")` (or `shutil.which(\"uv\")` for downstream distributions that flip USE_UV_EXECUTABLE) is None in the build environment: `pip install ./pkg`, `pip wheel`, `python -m build`, `uv build` with build isolation, and the hook then runs in an env whose PATH lacks the directory containing the uv-build script.","commonSituations":"PATH not including the interpreter's scripts/bin directory inside build isolation; installing with `pip install --target` or `--prefix` so the executable lands outside any PATH dir; a venv created without scripts on PATH; downstream packaging (Debian/Nix) that rebuilt `uv_build` with USE_UV_EXECUTABLE=True but did not ship `uv` on PATH; CI images that sanitize PATH.","solutions":["In the same environment run `python -c \"import shutil; print(shutil.which('uv-build'))\"` (or 'uv') to confirm the lookup fails and see which binary name is expected.","Install uv properly so the executable lands in the interpreter's scripts dir: `python -m pip install uv-build` (or the official installer), then prepend that scripts dir to PATH.","If build isolation strips PATH, install the backend in the outer env and build with `--no-build-isolation` (`pip install --no-build-isolation -e .`).","For downstream distributions: keep `uv` on PATH if you build with USE_UV_EXECUTABLE=True, otherwise ship the `uv-build` executable alongside the package."],"exampleFix":"# before: build isolation PATH lacks the backend binary\n$ pip install ./pkg\nRuntimeError: uv-build was not properly installed\n\n# after: make the executable resolvable, then rebuild\n$ python -m pip install uv-build\n$ python -c \"import shutil; print(shutil.which('uv-build'))\"  # prints a path\n$ pip install ./pkg","handlingStrategy":"validation","validationCode":"import shutil, sysconfig\n\nscripts_dir = sysconfig.get_path(\"scripts\")\nexpected = \"uv\" if False else \"uv-build\"  # match USE_UV_EXECUTABLE for your distro\nif shutil.which(expected) is None:\n    raise SystemExit(\n        f\"{expected} not on PATH; install uv/uv-build and add {scripts_dir} to PATH before building\"\n    )","typeGuard":null,"tryCatchPattern":"# PEP 517 frontend / wrapper around the backend hooks\ntry:\n    subprocess.run([sys.executable, \"-m\", \"pip\", \"wheel\", \".\", \"--no-deps\"], check=True)\nexcept subprocess.CalledProcessError as exc:\n    if \"was not properly installed\" in (exc.stderr or \"\"):\n        # binary missing in build env: install it or disable build isolation\n        subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"uv-build\"], check=True)\n        subprocess.run([sys.executable, \"-m\", \"pip\", \"wheel\", \".\", \"--no-deps\", \"--no-build-isolation\"], check=True)\n    else:\n        raise","preventionTips":["Pin `uv_build` (and uv) in [build-system].requires so build isolation installs a version whose binary ships with the wheel.","In Docker/CI, run `uv --version` and `python -c \"import shutil; print(shutil.which('uv-build'))\"` as a smoke test before any build step.","Prefer `uv build` as the frontend when available; it guarantees the backend binary is reachable."],"tags":["build-backend","pep-517","packaging","environment","path"],"backgroundTag":null,"analyzedSha":"f1a42680ff5272232d65748acf338b19778dde24","analyzedAt":"2026-08-16T04:51:47.599Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}