{"record":{"id":"b1bf4c3c69e7a3ee","repo":"Significant-Gravitas/AutoGPT","slug":"otto-api-request-failed-error-text","errorCode":null,"errorMessage":"Otto API request failed: {error_text}","messagePattern":"Otto API request failed: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":null,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/otto/service.py","lineNumber":115,"sourceCode":"                    \"message_id\": request.message_id,\n                }\n\n                if graph_data:\n                    payload[\"graph_data\"] = graph_data.model_dump()\n\n                logger.info(f\"Sending request to Otto API for user {user_id}\")\n                logger.debug(f\"Request payload: {payload}\")\n\n                async with session.post(\n                    OTTO_API_URL,\n                    json=payload,\n                    headers=headers,\n                    timeout=aiohttp.ClientTimeout(total=60),\n                ) as response:\n                    if response.status != 200:\n                        error_text = await response.text()\n                        logger.error(f\"Otto API error: {error_text}\")\n                        raise HTTPException(\n                            status_code=response.status,\n                            detail=f\"Otto API request failed: {error_text}\",\n                        )\n\n                    data = await response.json()\n                    logger.info(\n                        f\"Successfully received response from Otto API for user {user_id}\"\n                    )\n                    return ApiResponse(**data)\n\n        except aiohttp.ClientError as e:\n            logger.error(f\"Connection error to Otto API: {str(e)}\")\n            raise HTTPException(\n                status_code=503, detail=\"Failed to connect to Otto service\"\n            )\n        except asyncio.TimeoutError:\n            logger.error(\"Timeout error connecting to Otto API after 60 seconds\")\n            raise HTTPException(","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/otto/service.py#L97-L133","documentation":"Raised inside OttoService.ask when the upstream Otto API answers with a non-200 status; the proxy forwards that same status code to the client with the upstream error body embedded in the detail. It reflects an upstream rejection (4xx/5xx from Otto itself), not a transport failure.","triggerScenarios":"POST to the chat route while Otto returns 400 (malformed payload/graph data), 401/403 (Otto auth misconfigured), 429 (rate limited), or 5xx (Otto internal error). The forwarded status is whatever Otto returned.","commonSituations":"Schema drift between this backend and the Otto API causing 400s; expired or missing credentials on the Otto side; Otto overloaded returning 503/429; user-supplied graph data producing upstream validation errors.","solutions":["Read the error_text in the detail and backend logs — it is Otto's own error message and pinpoints the cause.","If 400: compare the request payload schema against the Otto API version deployed; fix payload construction.","If 401/403/429: fix Otto-side credentials or back off and retry respecting rate limits.","Pin/align the Otto API version with the backend release so the contract matches."],"exampleFix":"// before — raw upstream body forwarded to clients\nraise HTTPException(status_code=response.status, detail=f\"Otto API request failed: {error_text}\")\n// after — sanitize and log the body, return a stable message\nlogger.error(f\"Otto API {response.status}: {error_text}\")\nraise HTTPException(status_code=502, detail=\"Otto upstream request failed\")","handlingStrategy":"fallback","validationCode":"// Validate the chat payload shape before sending through the proxy\nif (!req?.message || typeof req.message !== 'string') throw new TypeError('invalid ChatRequest');","typeGuard":"function isChatRequest(o: unknown): o is ChatRequest {\n  return !!o && typeof (o as ChatRequest).message === 'string';\n}","tryCatchPattern":"try { return await otto.ask(req); }\ncatch (e) {\n  if ([400, 429].includes(e.status)) { /* fix payload / back off */ }\n  else if (e.status >= 500) { return fallbackAnswer; } // degraded mode\n  else throw e;\n}","preventionTips":["Pin the Otto API version deployed alongside the backend.","Log upstream status+body server-side; never show raw error_text to end users.","Rate-limit client retries to avoid hammering an unhealthy upstream."],"tags":["upstream","proxy","http-4xx","http-5xx","otto"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}