{"record":{"id":"5f358dabedb117ad","repo":"Significant-Gravitas/AutoGPT","slug":"request-to-otto-service-timed-out","errorCode":null,"errorMessage":"Request to Otto service timed out","messagePattern":"Request to Otto service timed out","errorType":"http","errorClass":"HTTPException","httpStatus":504,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/otto/service.py","lineNumber":133,"sourceCode":"                        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(\n                status_code=504, detail=\"Request to Otto service timed out\"\n            )\n        except Exception as e:\n            logger.error(f\"Unexpected error in Otto API proxy: {str(e)}\")\n            raise HTTPException(\n                status_code=500, detail=\"Internal server error in Otto proxy\"\n            )\n","sourceCodeStart":115,"sourceCodeEnd":141,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/otto/service.py#L115-L141","documentation":"Raised by OttoService.ask when the upstream Otto API does not respond within the 60-second total aiohttp timeout (asyncio.TimeoutError is caught and mapped to a 504). It means the upstream accepted the connection but was too slow to complete the response.","triggerScenarios":"Chat requests where Otto takes longer than the 60s ClientTimeout(total=60) — long-running LLM generation, Otto stuck waiting on its own dependencies, or degraded upstream performance under load.","commonSituations":"Large graph payloads making Otto slow; Otto's own model/DB bottleneck; occasional tail-latency spikes that exceed the fixed budget; clients without their own timeout retrying and stacking load.","solutions":["Check Otto service latency/health — a 60s+ response usually means the upstream is degraded or the request is too heavy.","Reduce payload size (e.g. trim graph data) or split the request if Otto processes large contexts slowly.","If long responses are expected, raise the aiohttp ClientTimeout and any intermediate proxy timeouts to match.","Add client-side timeout handling and avoid immediate tight retries that amplify upstream load."],"exampleFix":"# before\ntimeout=aiohttp.ClientTimeout(total=60)\n# after — budget aligned with expected Otto latency\ntimeout=aiohttp.ClientTimeout(total=120, connect=5)","handlingStrategy":"retry","validationCode":"// Client-side: cap own timeout under the server's 60s so users get feedback first\nconst ctrl = new AbortController();\nsetTimeout(() => ctrl.abort(), 50_000);","typeGuard":null,"tryCatchPattern":"try { return await otto.ask(req); }\ncatch (e) {\n  if (e.status === 504) { // only retry once; timeouts often mean upstream overload\n    return await otto.ask(req);\n  }\n  throw e;\n}","preventionTips":["Show streaming/progress UI so users don't abandon and re-fire long requests.","Trim large graph payloads before proxying.","Set gateway/LB timeouts >= the backend's 60s budget to avoid double timeouts."],"tags":["timeout","http-504","aiohttp","otto","performance"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}