BerriAI/litellm · error · LangGraphError

str(await response.aread())

Error message

str(await response.aread())

What it means

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.

Source

Thrown at litellm/llms/langgraph/chat/transformation.py:371

        )
        from litellm.utils import CustomStreamWrapper

        if client is None or not isinstance(client, AsyncHTTPHandler):
            client = get_async_httpx_client(llm_provider=cast(Any, "langgraph"), params={})

        verbose_logger.debug("Making async streaming request to: %s", api_base)

        # Make async streaming request
        response: Final = await client.post(
            api_base,
            headers=headers,
            data=json.dumps(data),
            stream=True,
            logging_obj=logging_obj,
        )

        if response.status_code != 200:
            raise LangGraphError(status_code=response.status_code, message=str(await response.aread()))

        # Create iterator for SSE stream
        completion_stream: Final = self.get_streaming_response(model=model, raw_response=response)

        streaming_response: Final = CustomStreamWrapper(
            completion_stream=completion_stream,
            model=model,
            custom_llm_provider=custom_llm_provider,
            logging_obj=logging_obj,
        )

        # LOGGING
        logging_obj.post_call(
            input=messages,
            api_key="",
            original_response="first stream response received",
            additional_args={"complete_input_dict": data},
        )

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Inspect the exception's message (the raw server body) and status_code to classify the failure
  2. Fix auth (401/403): update LANGGRAPH_API_KEY / api_key
  3. Fix routing (404): correct the graph name in the model string
  4. Fix payload (422): match the graph's expected input schema
  5. Add retry with backoff for transient 5xx during deployments
Defensive patterns

Strategy: retry

Validate before calling

async def langgraph_async_endpoint_ok(api_base: str, api_key: str) -> bool:
    import httpx
    async with httpx.AsyncClient(timeout=10) as client:
        r = await client.get(
            f"{api_base.rstrip('/')}/info",
            headers={"Authorization": f"Bearer {api_key}"},
        )
        return r.status_code == 200

Try / catch

async def stream_with_retry(make_call, attempts=3):
    for i in range(attempts):
        try:
            return await make_call()
        except LangGraphError as e:
            if e.status_code >= 500 and i < attempts - 1:
                await asyncio.sleep(2**i)
                continue
            raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/8625310532a42c75. Report an issue: GitHub.