{"record":{"id":"65e1a3d4bb6846df","repo":"BerriAI/litellm","slug":"failed-to-connect-to-braintrust-api-str-e","errorCode":null,"errorMessage":"Failed to connect to Braintrust API: {str(e)}","messagePattern":"Failed to connect to Braintrust API: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":502,"severity":"error","filePath":"cookbook/litellm_proxy_server/braintrust_prompt_wrapper_server.py","lineNumber":216,"sourceCode":"        \"Authorization\": f\"Bearer {braintrust_token}\",\n        \"Accept\": \"application/json\",\n    }\n    print(f\"headers: {headers}\")\n    print(f\"braintrust_url: {braintrust_url}\")\n    print(f\"braintrust_token: {braintrust_token}\")\n\n    try:\n        async with httpx.AsyncClient(timeout=30.0) as client:\n            response = await client.get(braintrust_url, headers=headers)\n            response.raise_for_status()\n            braintrust_data = response.json()\n    except httpx.HTTPStatusError as e:\n        raise HTTPException(\n            status_code=e.response.status_code,\n            detail=f\"Braintrust API error: {e.response.text}\",\n        )\n    except httpx.RequestError as e:\n        raise HTTPException(\n            status_code=502,\n            detail=f\"Failed to connect to Braintrust API: {str(e)}\",\n        )\n    except json.JSONDecodeError as e:\n        raise HTTPException(\n            status_code=502,\n            detail=f\"Failed to parse Braintrust API response: {str(e)}\",\n        )\n\n    print(f\"braintrust_data: {braintrust_data}\")\n    # Transform the response\n    try:\n        transformed_data = transform_braintrust_response(braintrust_data)\n        print(f\"transformed_data: {transformed_data}\")\n        return JSONResponse(content=transformed_data)\n    except Exception as e:\n        raise HTTPException(\n            status_code=500,","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/cookbook/litellm_proxy_server/braintrust_prompt_wrapper_server.py#L198-L234","documentation":"The async counterpart of the sync streaming error: raised when iterating an async text-completion stream (async for transformed_chunk in streamwrapper) throws. Exceptions during async chunk delivery - connection resets, provider error events, parsing failures - are caught and re-raised as OpenAIError with upstream status_code, headers, and text. The 'error_text' placeholder message means the caught exception had no .text attribute, so str(e) was used.","triggerScenarios":"Using await litellm.atext_completion(..., stream=True) (or the async iterator) when the aiohttp/httpx connection drops mid-stream, the provider emits an error event after headers were sent, or a chunk violates the expected schema during async parsing.","commonSituations":"Async web servers (FastAPI) proxying streams under load; event-loop friendly code hitting the same mid-stream failures as sync but surfacing CancelledError-adjacent connection errors; timeouts from async clients with defaults too small.","solutions":["Wrap the async for loop in try/except OpenAIError and inspect .status_code/.message.","Set timeout and num_retries on the async call; ensure the event loop is not blocked elsewhere, starving the stream reader.","For recurring mid-stream drops, increase client timeouts and check proxy idle-timeout settings.","Degrade gracefully to a non-streaming call on repeated stream failures if partial output is unacceptable."],"exampleFix":"# before\nasync for chunk in await litellm.atext_completion(model=..., prompt=..., stream=True):\n    await handle(chunk)\n\n# after\ntry:\n    async for chunk in await litellm.atext_completion(model=..., prompt=..., stream=True):\n        await handle(chunk)\nexcept litellm.exceptions.OpenAIError as e:\n    logger.error(\"async stream failed: %s (%s)\", e.message, e.status_code)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"from litellm.exceptions import OpenAIError\n\ndef is_async_stream_error(e: BaseException) -> bool:\n    return isinstance(e, OpenAIError) and getattr(e, \"status_code\", None) is not None","tryCatchPattern":"from litellm.exceptions import OpenAIError\n\ntry:\n    async for chunk in await litellm.atext_completion(model=..., prompt=..., stream=True):\n        await handle(chunk)\nexcept OpenAIError as e:\n    logger.error(\"async stream failed: %s (%s)\", e.message, e.status_code)\n    raise","preventionTips":["Keep the event loop unblocked so the async stream reader is serviced promptly.","Set explicit async timeouts; do not rely on defaults for long generations.","Fall back to non-streaming async calls when streams repeatedly fail."],"tags":["openai","async","streaming","text-completion","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}