Skip to content

fix: arm emergency shrink on upstream failure to break relay-5xx deadlock (#11) - #229

Open
ranxianglei wants to merge 1 commit into
masterfrom
2026-08-24_fix-relay-5xx-deadlock
Open

fix: arm emergency shrink on upstream failure to break relay-5xx deadlock (#11)#229
ranxianglei wants to merge 1 commit into
masterfrom
2026-08-24_fix-relay-5xx-deadlock

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Problem (#11)

zcode user on a justwoker relay channel: every request for claude-opus-5 returns 500 after installing bili. Log shows:

  • {"error":{"type":"new_api_error","message":"upstream error: do request failed"}} — the relay's own error (relay → its upstream failed), fixed ~31s timeout, plus one Cloudflare 522
  • The session was huge: 676 messages, ~250K tokens vs a 200K window
  • Other channels in the same log (openrouter ox-alpha, opencode.ai) worked fine, EMERGENCY compression fired there

Deadlock: compression triggering depends on the upstream usage report (lastInputTokens). A failed request never reports usage → the proxy re-sends the same ~250K payload on every retry → the relay fails it again → forever. The session can never recover through bili.

Fix

Arm the emergency shrink on failures with a local estimate of the body actually sent:

  • armFailureShrink() (src/server.ts) — estimateTokensFast(body) raises session.stats.lastInputTokens if larger, then markDirty (error paths return before forward()'s trailing save). Deliberate exception to the "tokenCount must be real usage" invariant: it only RAISES the value (lower bound → compress earlier, never later), the kernel no-ops below truncate.threshold, and the next successful usage report overwrites it.
  • Fires on: upstream 5xx responses (generic relay errors carry no overflow signature, so this is the only self-heal path) and network-level fetch failures (socket reset, timeout abort) for non-GET/HEAD.
  • Excluded: 4xx (auth/quota errors must not distort the usage signal); overflow 400s keep the existing learned-window path.

Next turn, processTurn sees usage ≥100% → the kernel's emergency nudge + emergency-truncate node truncate large old tool results server-side (no model cooperation — critical, because the model never responds in this state). The resent payload shrinks below the relay's tolerance and the session recovers.

Tests

tests/e2e-relay-5xx-selfheal.test.ts (2 new e2e tests, mirroring the overflow-selfheal harness):

  1. 500 → arm → truncate → recover: oversized history → relay 500 (passed through verbatim) → session armed with local estimate → next request's forwarded payload contains [truncated for context space], shrank, upstream 200 → real usage report overwrites the armed value
  2. 401 does NOT arm: auth errors leave lastInputTokens untouched

Full suite: 567 tests pass, typecheck + build clean.

…lock (#11)

A failed request (relay 5xx, network error) never reports usage, so
lastInputTokens stays frozen and every retry re-sends the same oversized
payload — the relay fails it again. On 5xx and network-level failures,
arm the emergency shrink with a local estimate of the body just sent:
the next turn's processTurn fires the kernel's emergency nudge and
tool-result truncate server-side, shrinking the payload without model
cooperation. 4xx responses are excluded (auth/quota errors must not
distort the usage signal).
@github-actions

Copy link
Copy Markdown

📦 Built Package Artifact

Branch: 2026-08-24_fix-relay-5xx-deadlock (06666f0)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-229

Each push to this PR publishes a new version under the pr-229 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr229.tgz
npm install -g package

This comment is automatically updated on each push.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant