{"record":{"id":"c7030574692eaba3","repo":"headroomlabs-ai/headroom","slug":"httpx-is-required-for-headroom-cloud-mode-pip-ins-c70305","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/litellm_callback.py","lineNumber":182,"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":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/integrations/litellm_callback.py#L164-L200","documentation":"Raised in litellm_callback._cloud_compress(): when Headroom's LiteLLM callback is configured for Cloud mode (managed CCR/TOIN/analytics via the Headroom SaaS API) and the lazy `import httpx` inside the method fails. Headroom makes httpx optional and only imports it when the first cloud compression request is attempted, so the error surfaces at request time, not at callback registration.","triggerScenarios":"Creating the LiteLLM callback with cloud mode enabled (api_key/api_url set so _cloud_compress is used) and then sending a completion request through LiteLLM in an environment without httpx installed; _client is None on first call, triggering the lazy import path.","commonSituations":"Using `headroom[litellm]` or plain headroom without the cloud extra; deployments that enabled Headroom Cloud (X-Headroom-Key auth) but whose image lacks httpx; assuming the callback's import-time success means all deps are present — httpx is deferred so it slips through import checks.","solutions":["Install httpx: `pip install httpx` (or add it to your deployment dependencies)","Prefer the bundled extra if provided: `pip install 'headroom[cloud]'` or equivalent","Verify before traffic: `python -c \"import httpx\"` in the same environment that runs LiteLLM"],"exampleFix":"# before\nfrom headroom.integrations.litellm_callback import HeadroomCallback\ncb = HeadroomCallback(cloud_api_key='...')  # fails at first completion without httpx\n\n# after\n# pip install httpx\nfrom headroom.integrations.litellm_callback import HeadroomCallback\ncb = HeadroomCallback(cloud_api_key='...')","handlingStrategy":"validation","validationCode":"import importlib.util\nassert importlib.util.find_spec('httpx'), 'pip install httpx before enabling Headroom Cloud mode'","typeGuard":null,"tryCatchPattern":"try:\n    result = await litellm.acompletion(...)\nexcept ImportError as e:\n    if 'httpx' in str(e):\n        logger.error('Cloud compression disabled — missing httpx; continuing uncompressed')\n        raise","preventionTips":["Add httpx to requirements whenever the callback runs in cloud mode (api_key set)","Because the import is lazy, run a runtime dep probe at callback registration, not just at app import","Test one cloud-mode completion in staging before deploying"],"tags":["httpx","litellm","cloud","import-error","lazy-import"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}