{"record":{"id":"0146186be461ea44","repo":"ZhuLinsen/daily_stock_analysis","slug":"timeout-014618","errorCode":"timeout","errorMessage":"App Server request timed out: {method}","messagePattern":"App Server request timed out: (.+?)","errorType":"error_code","errorClass":"CodexAppServerError","httpStatus":null,"severity":"error","filePath":"src/agent/codex_app_server_transport.py","lineNumber":347,"sourceCode":"            deadline = min(deadline, self.deadline)\n        response_queue: queue.Queue = queue.Queue(maxsize=1)\n        with self._state_lock:\n            request_id = self._next_id\n            self._next_id += 1\n            self._pending[request_id] = response_queue\n        try:\n            self._write_message(\n                {\"id\": request_id, \"method\": method, \"params\": params},\n                deadline=deadline,\n                respect_cancellation=respect_cancellation,\n            )\n        except CodexAppServerError as exc:\n            with self._state_lock:\n                self._pending.pop(request_id, None)\n            if exc.code in {\"cancelled\", \"timeout\"}:\n                self._terminate_process()\n            if exc.code == \"timeout\":\n                raise CodexAppServerError(\n                    \"timeout\",\n                    f\"App Server request timed out: {method}\",\n                ) from exc\n            if exc.code == \"cancelled\":\n                raise CodexAppServerError(\n                    \"cancelled\",\n                    \"App Server request was cancelled\",\n                ) from exc\n            raise\n        while True:\n            self._raise_if_fatal()\n            if (\n                respect_cancellation\n                and self.cancel_event is not None\n                and self.cancel_event.is_set()\n            ):\n                with self._state_lock:\n                    self._pending.pop(request_id, None)","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/agent/codex_app_server_transport.py#L329-L365","documentation":"The JSON-RPC request() wrapper gives every call a monotonic deadline (request_timeout capped by the transport deadline). If writing the request frame to the app-server's stdin cannot complete within that deadline, the transport pops the pending request, terminates the process (a timed-out write means the pipe or process is wedged), and re-raises with code 'timeout' naming the failed method.","triggerScenarios":"The Codex App Server process is hung or blocked and not draining stdin; the per-request request_timeout or the overall remaining_timeout() budget (e.g. client.request_timeout = remaining_timeout()) is set too small; the writer lock is held by another stalled request; the process died without the reader noticing.","commonSituations":"Total turn budget nearly exhausted so remaining_timeout() is a fraction of a second when the next call is made; a slow model turn keeps the app-server busy so it stops reading stdin; OS-level backpressure on a full stdin pipe; concurrent requests serialized behind a stuck one.","solutions":["Increase request_timeout (and the overall deadline feeding remaining_timeout()) so each RPC has enough headroom","Check the budget before each call: skip follow-up calls once remaining_timeout() is below a minimum viable threshold instead of letting them time out","Investigate why the app-server is not draining stdin: capture its stderr, check CPU/memory, verify the binary version","After this error the transport is terminated; create a fresh transport/agent session rather than reusing the dead one"],"exampleFix":"# before\nclient.request_timeout = remaining_timeout()  # may be 0.05s at end of budget\nclient.request(\"turn/start\", params)\n\n# after\nleft = remaining_timeout()\nif left < MIN_RPC_BUDGET:  # e.g. 5.0\n    raise TimeoutError(f\"insufficient budget for next RPC: {left:.2f}s\")\nclient.request_timeout = left\nclient.request(\"turn/start\", params)","handlingStrategy":"retry","validationCode":"left = remaining_timeout()\nif left < MIN_RPC_BUDGET:\n    raise BudgetExhausted(f\"{left:.2f}s left, below the {MIN_RPC_BUDGET}s minimum per-RPC budget\")\nclient.request_timeout = left","typeGuard":null,"tryCatchPattern":"try:\n    client.request(method, params)\nexcept CodexAppServerError as exc:\n    if exc.code == \"timeout\":\n        client = rebuild_transport()  # process was terminated; fresh session required\n        return retry_once(client, method, params)\n    raise","preventionTips":["Budget-check remaining_timeout() before every RPC in the session flow","Give each RPC a timeout proportional to its real latency (turn/start needs far more than thread/start)","Log app-server stderr alongside timeouts to distinguish hung process from tight budget"],"tags":["codex","timeout","jsonrpc","process-management"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}