{"record":{"id":"0bdf689afa825867","repo":"headroomlabs-ai/headroom","slug":"tool-distributed-via-pypi-only-pip-install-he","errorCode":null,"errorMessage":"{tool}: distributed via PyPI only; `pip install headroom-ai` should have placed `{entry.get('binary', tool)}` on PATH.","messagePattern":"(.+?): distributed via PyPI only; `pip install headroom-ai` should have placed `(.+?)` on PATH\\.","errorType":"exception","errorClass":"PlatformNotSupported","httpStatus":null,"severity":"error","filePath":"headroom/binaries.py","lineNumber":211,"sourceCode":"\ndef _tool_entry(tool: str) -> dict[str, Any]:\n    reg = _registry()\n    tools: dict[str, Any] = reg.get(\"tools\", {})\n    if tool not in tools:\n        raise KeyError(f\"unknown tool {tool!r}; known: {sorted(tools)}\")\n    entry: dict[str, Any] = tools[tool]\n    return entry\n\n\ndef _is_pypi_tool(tool: str) -> bool:\n    entry = _tool_entry(tool)\n    return entry.get(\"version\") == \"pypi\" or not entry.get(\"assets\")\n\n\ndef _asset_for_platform(tool: str, plat: PlatformKey) -> dict[str, Any]:\n    entry = _tool_entry(tool)\n    if _is_pypi_tool(tool):\n        raise PlatformNotSupported(\n            f\"{tool}: distributed via PyPI only; `pip install headroom-ai` \"\n            f\"should have placed `{entry.get('binary', tool)}` on PATH.\"\n        )\n    assets: dict[str, Any] = entry.get(\"assets\", {})\n    asset: dict[str, Any] | None = assets.get(plat.key())\n    if asset is None:\n        supported = sorted(assets.keys())\n        raise PlatformNotSupported(\n            f\"{tool}: no prebuilt binary for {plat.key()}; supported: {supported}\"\n        )\n    return asset\n\n\ndef _mirror_url(url: str) -> str:\n    mirror = os.environ.get(\"HEADROOM_BINARIES_MIRROR\")\n    if not mirror:\n        return url\n    # Only substitute the github.com host so that paths remain intact.","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/binaries.py#L193-L229","documentation":"_asset_for_platform raises PlatformNotSupported when a tool is distributed via PyPI (registry entry has version 'pypi' or no assets) and therefore has no downloadable platform binary. The expectation is that 'pip install headroom-ai' already placed the entry's binary (entry['binary'], falling back to the tool name) on PATH; a fetch cannot fix its absence.","triggerScenarios":"Requesting a platform asset for a PyPI-distributed tool (e.g. a pure-Python console script) while running from a source checkout or an environment where the headroom package's scripts directory is not on PATH.","commonSituations":"Running from a git checkout without 'pip install -e .', a broken venv whose bin/ directory is not on PATH, or manually invoking the binaries module outside an installed package context.","solutions":["Install the package properly: pip install headroom-ai, which places the console script on PATH.","Verify the binary resolves: which <binary-name> (the name is printed in the error message).","If using a source checkout, pip install -e . so entry points are generated.","Ensure the venv's bin/ (or Scripts\\ on Windows) is on PATH."],"exampleFix":"# before\npython -c \"from headroom.binaries import ensure_binary; ensure_binary('some-pypi-tool')\"\n# PlatformNotSupported: distributed via PyPI only\n\n# after\npip install headroom-ai\nwhich some-pypi-tool  # resolves now","handlingStrategy":"validation","validationCode":"import shutil\n\ndef pypi_tool_on_path(binary: str) -> bool:\n    return shutil.which(binary) is not None\n\nif not pypi_tool_on_path(\"some-tool\"):\n    raise SystemExit(\"run `pip install headroom-ai`; its console scripts must be on PATH\")","typeGuard":null,"tryCatchPattern":"try:\n    path = ensure_binary(\"some-tool\")\nexcept PlatformNotSupported as e:\n    if \"distributed via PyPI only\" in str(e):\n        raise SystemExit(\"install headroom-ai into this environment; binary must be on PATH\") from e\n    raise","preventionTips":["Install headroom-ai (not just copy the source tree) in runtime environments.","After building images, verify console scripts resolve: which <tool>.","For source checkouts, use pip install -e . so entry points exist."],"tags":["python","binaries","pypi","platform-not-supported","packaging"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}