stablyai/orca · error · CodexAppServerTimeoutError
codex app-server session already timed out
Error message
codex app-server session already timed out
What it means
Thrown as CodexAppServerTimeoutError inside requestRpc when the session-wide deadline already fired (timedOut === true) before a new RPC call is made. The deadline timer sets timedOut and SIGKILLs the codex child; any subsequent requestRpc in the same session short-circuits with this message instead of writing into a dead pipe.
Source
Thrown at src/main/codex/codex-app-server-session.ts:233
function notify(method: string, params?: Record<string, unknown>): void {
const payload: Record<string, unknown> = { method }
if (params !== undefined) {
payload.params = params
}
try {
sendLine(payload)
} catch {
// Notifications are fire-and-forget; a dead child fails the next request.
}
}
async function requestRpc(method: string, params?: Record<string, unknown>): Promise<unknown> {
if (spawnError) {
throw spawnError
}
if (timedOut) {
throw new CodexAppServerTimeoutError('codex app-server session already timed out')
}
if (exited) {
throw buildEarlyExitError()
}
const id = nextRequestId++
const response = await new Promise<JsonRpcResponse>((resolve, reject) => {
pending.set(id, { resolve, reject })
const payload: Record<string, unknown> = { method, id }
if (params !== undefined) {
payload.params = params
}
try {
sendLine(payload)
} catch (error) {
pending.delete(id)
reject(error instanceof Error ? error : new Error(String(error)))
}
})View on GitHub (pinned to 1136503c6a)
Solutions
- Raise invocation.timeoutMs to cover the total number of sequential RPCs the body performs (not just one).
- Reduce the number of sequential awaits in the session body, or batch work (e.g., one config/batchWrite instead of several).
- Profile each RPC to find the slow one and optimize the codex-side workload (fewer hooks, smaller config).
- Start a fresh session for additional work rather than reusing a timed-out one.
Defensive patterns
Strategy: validation
Validate before calling
// Design the session body to fit within the deadline; track elapsed budget: const start = Date.now() const withinBudget = () => Date.now() - start < invocation.timeoutMs - RESERVE_MS // Structure the body so it stops issuing RPCs once withinBudget() is false.
Type guard
function isAlreadyTimedOutError(error: unknown): boolean {
return error instanceof Error && error.message === 'codex app-server session already timed out'
} Try / catch
try {
await runCodexAppServerSession(invocation, async (rpc) => {
// do all RPCs here; the session owns the deadline
})
} catch (error) {
if (isCodexAppServerTimeoutError(error)) {
// start a fresh session with a larger timeoutMs rather than reusing
}
} Prevention
- Set invocation.timeoutMs to exceed the total of all sequential RPCs in the body.
- Batch edits (one config/batchWrite) instead of many sequential writes.
- Start a new session for additional work rather than reusing an expired one.
- Avoid issuing RPCs after a long await in the same session body.
When it happens
Trigger: The body callback issued multiple sequential RPCs (initialize, hooks/list, config/batchWrite, hooks/list again) and an earlier await consumed the whole timeoutMs budget, so the next requestRpc sees timedOut already true; or the deadline fired during await and the next call detects it.
Common situations: A grant or heal body does several round-trips and the cumulative time exceeds invocation.timeoutMs; a slow first hooks/list eats the budget; the timeout was sized for fewer RPCs than the body performs.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- codex trust-grant entry produced no result (exit ${spawned.s
- codex app-server does not support ${method}: ${response.erro
- codex app-server ${method} failed: ${response.error.message
- codex trust-grant entry exceeded ${request.invocation.timeou
- codex trust-grant entry killed by ${spawned.signal} after ${
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/d7c37339a901718c.
Report an issue: GitHub.