{"record":{"id":"8625310532a42c75","repo":"BerriAI/litellm","slug":"str-await-response-aread","errorCode":null,"errorMessage":"str(await response.aread())","messagePattern":"str\\(await response\\.aread\\(\\)\\)","errorType":"http","errorClass":"LangGraphError","httpStatus":null,"severity":"error","filePath":"litellm/llms/langgraph/chat/transformation.py","lineNumber":371,"sourceCode":"        )\n        from litellm.utils import CustomStreamWrapper\n\n        if client is None or not isinstance(client, AsyncHTTPHandler):\n            client = get_async_httpx_client(llm_provider=cast(Any, \"langgraph\"), params={})\n\n        verbose_logger.debug(\"Making async streaming request to: %s\", api_base)\n\n        # Make async streaming request\n        response: Final = await client.post(\n            api_base,\n            headers=headers,\n            data=json.dumps(data),\n            stream=True,\n            logging_obj=logging_obj,\n        )\n\n        if response.status_code != 200:\n            raise LangGraphError(status_code=response.status_code, message=str(await response.aread()))\n\n        # Create iterator for SSE stream\n        completion_stream: Final = self.get_streaming_response(model=model, raw_response=response)\n\n        streaming_response: Final = CustomStreamWrapper(\n            completion_stream=completion_stream,\n            model=model,\n            custom_llm_provider=custom_llm_provider,\n            logging_obj=logging_obj,\n        )\n\n        # LOGGING\n        logging_obj.post_call(\n            input=messages,\n            api_key=\"\",\n            original_response=\"first stream response received\",\n            additional_args={\"complete_input_dict\": data},\n        )","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/langgraph/chat/transformation.py#L353-L389","documentation":"Async twin of the sync streaming guard: when an awaited POST to {api_base}/runs/stream returns a non-200 status, LiteLLM raises LangGraphError with that status code and the awaited body (await response.aread()) as the message. The body text is the LangGraph server's error detail and is the key to diagnosing the failure.","triggerScenarios":"Async streaming (litellm.acompletion(..., stream=True) with a langgraph/* model) where the server answers 401/403/404/422/5xx — bad API key, unknown assistant id, invalid run payload, or deployment outage.","commonSituations":"Using aiohttp-based async paths in FastAPI services against LangGraph Platform; rotated API keys not updated; renamed graphs after a refactor; transient 502/503 during LangGraph Cloud deploys.","solutions":["Inspect the exception's message (the raw server body) and status_code to classify the failure","Fix auth (401/403): update LANGGRAPH_API_KEY / api_key","Fix routing (404): correct the graph name in the model string","Fix payload (422): match the graph's expected input schema","Add retry with backoff for transient 5xx during deployments"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"async def langgraph_async_endpoint_ok(api_base: str, api_key: str) -> bool:\n    import httpx\n    async with httpx.AsyncClient(timeout=10) as client:\n        r = await client.get(\n            f\"{api_base.rstrip('/')}/info\",\n            headers={\"Authorization\": f\"Bearer {api_key}\"},\n        )\n        return r.status_code == 200","typeGuard":null,"tryCatchPattern":"async def stream_with_retry(make_call, attempts=3):\n    for i in range(attempts):\n        try:\n            return await make_call()\n        except LangGraphError as e:\n            if e.status_code >= 500 and i < attempts - 1:\n                await asyncio.sleep(2**i)\n                continue\n            raise","preventionTips":["Use the exception's status_code to separate permanent (4xx) from transient (5xx) failures in async handlers","Run an async /info health probe against the LangGraph deployment during service startup","Alert on repeated non-200 streams — it usually signals key rotation or a renamed graph, not load"],"tags":["langgraph","streaming","async","http"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}