Repository navigation
Description
Summary
bin/design-code-proxy.mjs dispatch has no timeout on its backend requests: if a backend accepts the connection (or connects and then stalls) and never answers, the client request hangs forever and the proxy's own primary→fallback machinery never fires — fallback only triggers on a socket error, an HTTP 429/5xx response, or an in-body quota error, and a silent backend produces none of those. Each hung request also holds one socket from the shared keep-alive pool (maxSockets: 32 per scheme) indefinitely, so a wedged backend can gradually exhaust the pool for the healthy backend too.
Evidence (main bd880194, file sha256 27e9fc8c…)
bin/design-code-proxy.mjs—tryTarget(indispatchWithFallback) builds the backend call withhttp.request({ hostname: '127.0.0.1', port: target.port, path: '/v1/chat/completions', agent: httpAgent, … })and registers onlylocalReq.on('error', …)→onFail. There is nolocalReq.setTimeout(...), notimeoutoption, and no abort anywhere in the dispatch path. The onlyAbortSignal.timeoutin the file is 2500 ms on the background/v1/modelscatalog probes (:95).- The AMR upstream forward in the same file (
clientReq = https.request(...), same handler) likewise sets no timeout; itserrorhandler falls back to local dispatch, which a hanging upstream also never triggers. - The fallback contract is otherwise proven working: a primary that answers 500 falls back immediately (see probe control below).
Probe (laptop, 2026-10-28, shipped file unmodified)
Probe dir: ~/git/fleet/probe-2026-10-28-laneB-designtimeout/ (laptop) — two stub backends (primary switchable 500/hang, fallback healthy) + the shipped proxy on alternate ports (ANTIGRAVITY_LS_PROXY_PORT/CODEX_PROXY_PORT/DESIGN_CODE_PROXY_PORT env):
- Control, healthy primary (
gpt-6-luna→ codex stub): 200 in 94 ms. - Control, primary answers 500 (
design-code-pro→ antigravity stub 500, codex stub healthy): 200 in 31 ms via fallback — the fallback machinery works when failure is signalled. - Test, primary accepts and never responds (
design-code-pro, primary in hang mode): no response within 8000 ms (client-sideAbortSignaltimeout fired); the healthy fallback was never tried. The proxy itself stayed alive (GET /v1/models→ 200 immediately after), so this is a per-request permanent wedge, not a crash.
Why it matters
dispatchWithFallback exists precisely so one bad backend doesn't take down design-code requests — the file already handles backend response errors, 429/5xx, and in-body quota errors (#681 fixed a sibling "hangs forever instead of falling back" bug in this same function). A backend that wedges silently (deadlocked language server, a proxy sibling stuck on its own upstream) is the remaining failure mode, and it is worse than a clean error: the client waits indefinitely and pooled sockets accumulate.
Acceptance criteria
- A backend that connects but does not respond within a bounded time (triage pins the value; it should be generous enough for slow streaming first-byte, e.g. a time-to-first-response / socket-inactivity timeout rather than a total-stream deadline) causes
onFail→ fallback, and if both targets time out, a clean 502 — never an indefinite hang. - The AMR upstream forward (
https.requestpath) gets the same treatment: a silent upstream falls back to local dispatch instead of hanging. - Streaming responses that are actively flowing are not killed by the timeout (inactivity-based, or reset on data).
- Tests in
bin/design-code-proxy.test.mjsstyle: hanging-primary → fallback serves; both-hang → 502 within a bounded time; slow-but-alive backend still succeeds. - Existing behaviours unchanged: 429/5xx fallback, in-body quota fallback, model rewriting on stream and non-stream paths.
Activity
developing-today commentedon Oct 29, 2026
CODE-1008
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
68 remaining items
dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
fix(design-code-proxy): retire failed targets so late errors cannot t…
fix(design-code-proxy): retired target that wrote the client head sti…
Merge pull request #4204 from developing-today/queue/5090-2097-design…
dezren39 commentedon Nov 2, 2026
🤖 Agent note · done