{"record":{"id":"be2e70efbc37d013","repo":"headroomlabs-ai/headroom","slug":"httpx-is-required-for-headroom-cloud-mode-pip-ins","errorCode":null,"errorMessage":"httpx is required for Headroom Cloud mode: pip install httpx","messagePattern":"httpx is required for Headroom Cloud mode: pip install httpx","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"headroom/integrations/asgi.py","lineNumber":212,"sourceCode":"            model=model or \"claude-sonnet-4-5-20250929\",\n            model_limit=self._model_limit,\n            hooks=self._hooks,\n        )\n        return {\n            \"messages\": result.messages,\n            \"tokens_before\": result.tokens_before,\n            \"tokens_after\": result.tokens_after,\n            \"tokens_saved\": result.tokens_saved,\n            \"compression_ratio\": result.compression_ratio,\n        }\n\n    async def _cloud_compress(self, messages: list[dict], model: str) -> dict[str, Any] | None:\n        \"\"\"Compress via Headroom Cloud API (managed CCR, TOIN, analytics).\"\"\"\n        if self._client is None:\n            try:\n                import httpx\n            except ImportError as e:\n                raise ImportError(\n                    \"httpx is required for Headroom Cloud mode: pip install httpx\"\n                ) from e\n            self._client = httpx.AsyncClient(timeout=30.0)\n\n        client = self._client\n        assert client is not None\n        resp = await client.post(\n            f\"{self._api_url}/v1/saas/compress\",\n            headers={\n                \"X-Headroom-Key\": self._api_key,\n                \"Content-Type\": \"application/json\",\n            },\n            content=json.dumps(\n                {\n                    \"messages\": messages,\n                    \"model\": model or \"claude-sonnet-4-5-20250929\",\n                    \"model_limit\": self._model_limit,\n                }","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/integrations/asgi.py#L194-L230","documentation":"Raised by the ASGI middleware's _cloud_compress when Headroom Cloud mode is enabled (an api_url/api_key configured) but httpx is not importable. The middleware defers the httpx import until the first cloud compression request, so an app can boot and serve local-mode traffic fine, then fail on the first request that actually needs the managed Cloud API. The fix named in the message is a plain pip install.","triggerScenarios":"Configuring the ASGI middleware with cloud/api_key settings in an environment where httpx was never installed; first request hitting the /v1/saas/compress path triggers the lazy import and raises. httpx installed in a different venv than the ASGI app produces the same result.","commonSituations":"Adding headroom[cloud]-style functionality to a slim FastAPI/Starlette deployment image; dependency extras skipped to shrink containers; local dev installs that never needed Cloud mode until the api_url was switched on.","solutions":["pip install httpx into the app's environment.","If Cloud mode was enabled by mistake, drop the cloud api_url/api_key config so the middleware stays on local compression (no httpx needed).","Add httpx to the deployment image requirements next to headroom.","Smoke-test after install by sending one request through the middleware and watching for a 200 from the cloud path."],"exampleFix":"# before\napp.add_middleware(HeadroomMiddleware, api_url=\"https://cloud.headroom.dev\", api_key=KEY)\n# first request -> ImportError: httpx is required\n\n# after\n$ python -m pip install httpx\napp.add_middleware(HeadroomMiddleware, api_url=\"https://cloud.headroom.dev\", api_key=KEY)","handlingStrategy":"validation","validationCode":"import importlib.util\n\nif cloud_mode_enabled and importlib.util.find_spec(\"httpx\") is None:\n    raise SystemExit(\"Headroom Cloud mode requires httpx: pip install httpx\")","typeGuard":null,"tryCatchPattern":"try:\n    response = await middleware_dispatch(request)\nexcept ImportError as e:\n    if \"httpx is required\" in str(e):\n        return JSONResponse({\"error\": \"headroom cloud dependency missing\"}, status_code=503)\n    raise","preventionTips":["Add httpx to deployment requirements whenever the middleware is configured with cloud api_url/api_key.","Startup smoke-test one cloud compression call so the lazy import fails at boot, not on user traffic.","In slim images, either ship httpx or explicitly run local-only mode."],"tags":["httpx","import-error","optional-dependency","asgi","cloud","lazy-import"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}