{"record":{"id":"a8bb43a6cf7a0f7b","repo":"BerriAI/litellm","slug":"failed-to-transform-braintrust-response-str-e","errorCode":null,"errorMessage":"Failed to transform Braintrust response: {str(e)}","messagePattern":"Failed to transform Braintrust response: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"cookbook/litellm_proxy_server/braintrust_prompt_wrapper_server.py","lineNumber":233,"sourceCode":"    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,\n            detail=f\"Failed to transform Braintrust response: {str(e)}\",\n        )\n\n\n@app.get(\"/health\")\nasync def health_check():\n    \"\"\"Health check endpoint.\"\"\"\n    return {\"status\": \"healthy\", \"service\": \"braintrust-prompt-wrapper\"}\n\n\n@app.get(\"/\")\nasync def root():\n    \"\"\"Root endpoint with service information.\"\"\"\n    return {\n        \"service\": \"Braintrust Prompt Wrapper for LiteLLM\",\n        \"version\": \"1.0.0\",\n        \"endpoints\": {","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/cookbook/litellm_proxy_server/braintrust_prompt_wrapper_server.py#L215-L251","documentation":"This is the get_error_class factory of LiteLLM's OpenAI Containers transformation: it constructs and raises a BaseLLMException carrying the HTTP status code, the error message, and the response headers extracted from a failed container-API HTTP response. The literal 'error_message' is the parameter name - the actual text comes from the upstream response body. It is LiteLLM's normalization point for non-2xx responses from OpenAI container endpoints (e.g. /v1/containers file operations).","triggerScenarios":"Calling litellm container/file APIs (e.g. retrieving binary file content from a container) when OpenAI returns a non-2xx status: 401 invalid key, 404 unknown container or file id, 400 bad request, or 429 rate limiting. The HTTP handler extracts status/body/headers and routes them through this factory to raise BaseLLMException.","commonSituations":"Using an expired or scoped-down API key that lacks container access; referencing a container_id or file_id from another project/org; preview API changes to the containers endpoints; uploading then immediately downloading files before processing completes.","solutions":["Catch litellm.exceptions.BaseLLMException (or litellm.APIError) and read .status_code, .message, .headers.","404: verify container_id/file_id exists in the same org/project as the key.","401/403: confirm the key is valid and has container API access.","Check .headers for retry-after on 429 and back off accordingly."],"exampleFix":"# before\ncontent = litellm.get_container_file_content(...)\n\n# after\ntry:\n    content = litellm.get_container_file_content(...)\nexcept litellm.exceptions.BaseLLMException as e:\n    if e.status_code == 404:\n        raise FileNotFoundError(e.message) from e\n    raise","handlingStrategy":"try-catch","validationCode":"def container_file_url_ok(container_id: str, file_id: str) -> bool:\n    return container_id.startswith(\"ctr_\") and file_id.startswith(\"file-\")","typeGuard":"from litellm.llms.base_llm.chat.transformation import BaseLLMException\n\ndef is_container_api_error(e: BaseException) -> bool:\n    return isinstance(e, BaseLLMException)","tryCatchPattern":"from litellm.exceptions import APIError\n\ntry:\n    content = litellm.get_container_file_content(...)\nexcept APIError as e:\n    sc = getattr(e, \"status_code\", None)\n    if sc == 404:\n        raise FileNotFoundError(str(e)) from e\n    if sc == 429:\n        retry_after = float(getattr(e, \"headers\", {}).get(\"retry-after\", 5))\n        time.sleep(retry_after)\n    raise","preventionTips":["Validate container_id/file_id format and ownership before requests.","Cache id-to-project mappings to avoid cross-org 404s.","Honor retry-after headers on container API rate limits."],"tags":["openai","containers","api-error","litellm","http"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}