Skip to content

codex-proxy: exec transports have no turn deadline — a hung codex exec child hangs the request forever and is never killed #2157

Closed

Description

@dezren39

Problem

bin/codex-proxy.mjs's exec transports have no turn deadline. runCodexOnce (bin/codex-proxy.mjs:803, spawn at :815) returns a promise that settles only from the child's close handler (:921) or a synchronous spawn throw — there is no timer anywhere in the function. Both exec call sites await it directly: the warm-resume attempt (:1219) and the cold full-history run (:1242). If the spawned codex exec child hangs — alive but never finishing its turn (upstream stall, a CLI waiting on something, a wedged session resume) — the HTTP request hangs forever, the child process is never killed, and the promise never settles. The only recovery is the client giving up; even then nothing in runCodexOnce kills the child on client disconnect (no res.on('close') hook reaches it — onSpawn only registers the child for the caller's bookkeeping).

Every sibling path in the same file, and in the sibling proxies, is bounded:

  • The app-server transport in this same file: connect timeout 10s (:504), JSON-RPC timeout 30s (:635-641).
  • bin/claude-code-proxy.mjs: TURN_TIMEOUT_MS = 300 * 1000 (:55) applied to its spawned turns (:455-461), with a SIGKILL escalation 3s after the deadline (:480).
  • bin/muse-proxy.mjs's warm path: WARM_TURN_TIMEOUT_MS = 300 * 1000 (:300, applied :585-587).

The exec fallback is precisely the path taken when the bounded app-server path has already failed — i.e. when the backend is already misbehaving — and it is the one path with no bound at all.

Evidence (verified this run, main b2b885b9)

Sandbox probe with a fake codex binary ($HOME/.local/bin/codex under a scratch HOME; the fake answers debug models with garbage so the static catalog floor is used, and sleeps 60s for any other invocation), CODEX_PROXY_TRANSPORT=exec:

  • Proxy log: Spawning: .../codex exec --json --skip-git-repo-check ... -m gpt-5.6-luna ... — the request reached runCodexOnce's spawn.
  • curl -X POST /v1/chat/completions (non-streaming): no response after 8s (curl killed by timeout 8, exit 124, 0 response bytes) while the fake child (sleep 60) was still running. Nothing in the proxy would have ended the request before the child's own exit at 60s — and a truly hung child never exits.

Dedup: gh searches for codex-proxy exec timeout, runCodexOnce, and codex-proxy hang (open + closed) return no covering issue. Adjacent but distinct: #2097/#2100/#2102 are the same no-timeout class in design-code-proxy, clef-proxy, and antigravity-ls-proxy (HTTP fetch / RPC paths in other files); the muse-proxy exec path has the same defect and is filed separately this run.

Why it matters

code-queue workers and OpenCode sessions route real coding turns through this proxy. One hung codex exec child wedges its request indefinitely and leaks a process; repeated hangs accumulate children and stall every caller queued behind them, with no log line or error to act on. The fallback path exists for resilience — unbounded, it converts a backend stall into a permanent proxy-side hang.

Acceptance criteria

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. added
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    effort/sSmall: expected under 2 hours of work
    app/codex-proxybin/codex-proxy.mjs fleet proxy
    on Oct 29, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator-code-a (Lane A)
    • Session / ID: cron job new-issue-creator-code-a, run 2026-10-29T06:48Z
    • Found via: filed this run
    • Task: Filed after verifying with a fake hanging codex binary that the exec transports (runCodexOnce) have no turn deadline — request unsettled at 8s, child never killed — while the app-server path in the same file and both sibling proxies bound their turns.
    • Expectation: effort/s — triage pins the deadline value/source, then a small-fix adds deadline + disconnect kill with fake-child regression tests.
    • Links: packet queue-pilot/packet-2157-triage.json (repo-health-code-pilot)
  5. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Cross-link: the muse-proxy exec fallback path has the same no-deadline defect and is filed as #2159 (verified the same way this run). The two fixes can share the deadline convention pinned in triage.

  6. 63 remaining items

  7. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  8. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    task: 8808
    state: handed off
    event: handed_off
    lane: opencode
    execution_lane: opencode
    session_id: ses_e5e58cf03bbffeNSSiAFL9ZcVC
    note: OpenCode claimant launched and bound this worker session before sending the task packet.

  11. developing-today commented on Nov 4, 2026

    @developing-today
    Contributor

    🤖 Agent note · handed off

    • Agent: OpenCode claimant (opencode-claimant)
    • Queue task: task 8808 (repo-health-code-pilot, worker repo-worker-code)
    • Issue: #2157
    • Session: ses_e5e58648c8bffeAkJejxNl5nwB
    • Route: opencode-route/workhorse; agent build
    • Expectation: this bound session works only task 8808, revalidates fresh state, heartbeats, and records a terminal queue state with this same session id.
  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/codex-proxybin/codex-proxy.mjs fleet proxyeffort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:donetask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions