{"record":{"id":"b6668d2cf7fd62f5","repo":"ZhuLinsen/daily_stock_analysis","slug":"resource-limit-exceeded","errorCode":"resource_limit_exceeded","errorMessage":"App Server exceeded the cumulative item budget","messagePattern":"App Server exceeded the cumulative item budget","errorType":"error_code","errorClass":"CodexAppServerError","httpStatus":null,"severity":"error","filePath":"src/agent/codex_app_server_transport.py","lineNumber":519,"sourceCode":"            notification = self._wait_for_turn(\n                thread_id,\n                turn_id,\n                self.request_timeout if timeout is None else timeout,\n                cancel_event=cancel_event,\n            )\n        except CodexAppServerError as exc:\n            raise CodexAppServerError(exc.code, str(exc), turn_started=True) from exc\n        completed_turn = notification.get(\"params\", {}).get(\"turn\") or {}\n        status = str(completed_turn.get(\"status\", \"unknown\"))\n        terminal_items = completed_turn.get(\"items\", [])\n        if not isinstance(terminal_items, list):\n            raise CodexAppServerError(\n                \"protocol_error\",\n                \"turn/completed returned a non-list items field\",\n                turn_started=True,\n            )\n        if len(terminal_items) > MAX_TURN_ITEM_COUNT:\n            raise CodexAppServerError(\n                \"resource_limit_exceeded\",\n                \"App Server exceeded the cumulative item budget\",\n                turn_started=True,\n            )\n        if status != \"completed\":\n            error = completed_turn.get(\"error\") or {}\n            info = error.get(\"codexErrorInfo\")\n            if status == \"interrupted\":\n                code = \"cancelled\"\n            else:\n                normalized_info = str(info or \"\").strip().casefold()\n                code = \"login_required\" if normalized_info == \"unauthorized\" else \"unknown_backend_error\"\n            message = redact_diagnostic_value(\n                error.get(\"message\", f\"Turn ended with status {status}\"),\n                limit=500,\n            )\n            raise CodexAppServerError(code, message, turn_started=True)\n        with self._state_lock:","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/agent/codex_app_server_transport.py#L501-L537","documentation":"run_turn() enforces MAX_TURN_ITEM_COUNT (1024) on the cumulative items returned by turn/completed. If the app-server accumulates more items than this budget (extra items are also tracked per notification in the reader thread), it raises code 'resource_limit_exceeded' with turn_started=True to bound memory and transcript size.","triggerScenarios":"A runaway agent loop where the model calls tools repeatedly without converging, producing >1024 items in one turn; a server bug duplicating items in the completion payload; prompts that encourage excessive step-by-step decomposition within a single turn.","commonSituations":"Analysis tasks with unbounded tool loops (e.g. the model keeps requesting data with slightly different parameters); a tool that returns errors causing infinite retry behavior by the model; raising the budget-sensitive workload without tuning prompts or max_tool_calls.","solutions":["Lower request.max_steps / max_tool_calls so the turn is cut off by step budget before item count explodes","Tighten the agent prompt to require convergence and cap repeated tool calls for the same goal","Check whether a specific tool's error output is triggering model retry loops and fix that tool's contract","If genuinely needed, negotiate a higher MAX_TURN_ITEM_COUNT — but treat 1024+ items in one turn as a design smell first"],"exampleFix":"# before\nrequest = AgentRequest(..., max_steps=200)  # model can emit 1000+ tool items\n\n# after\nrequest = AgentRequest(..., max_steps=24)  # converge before the 1024-item budget","handlingStrategy":"validation","validationCode":"if request.max_steps * ESTIMATED_ITEMS_PER_STEP > MAX_TURN_ITEM_COUNT:\n    request = replace(request, max_steps=MAX_TURN_ITEM_COUNT // ESTIMATED_ITEMS_PER_STEP)\n# and fail fast if remaining budget cannot fit a converging turn","typeGuard":"def within_item_budget(item_count: int, limit: int = 1024) -> bool:\n    return item_count <= limit","tryCatchPattern":"try:\n    turn = client.run_turn(thread_id, text, timeout=t)\nexcept CodexAppServerError as exc:\n    if exc.code == \"resource_limit_exceeded\":\n        return AnalysisOutcome.diverged(\"turn exceeded item budget; tighten max_steps and prompts\")\n    raise","preventionTips":["Set max_steps/max_tool_calls low enough that items cannot approach 1024","Prompt for convergence; forbid repeated identical tool calls","Watch item counts per turn in metrics to catch divergence trends early"],"tags":["codex","resource-limits","agent-loop","budget"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}