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
- 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
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
- 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
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
- str(response.read())
- Failed to connect to Braintrust API: {str(e)}
- _body (masked response body)
- {e.response.text}
- {response.text}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/8625310532a42c75.
Report an issue: GitHub.