Skip to content

fix(proxy): account for Responses WebSocket compaction errors - #1518

Draft
ROOOO wants to merge 3 commits into
ding113:devfrom
ROOOO:codex/ws-compaction-error-accounting
Draft

ROOOO wants to merge 3 commits into
ding113:devfrom
ROOOO:codex/ws-compaction-error-accounting

Conversation

@ROOOO

@ROOOO ROOOO commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix incorrect success accounting for Responses WebSocket requests that fail during raw compaction. Upstream error and response.failed events were being recorded as successful HTTP 200 requests because the raw compaction path skipped response-body diagnostics. This is the final PR in a three-part series fixing Responses WebSocket reliability.

Problem

Genuine upstream WebSocket error and response.failed events can be recorded as successful HTTP 200 requests during raw Responses compaction because that path skips general response-body diagnostics. This means circuit breakers, rate limiters, and usage accounting see a "success" when the upstream actually failed, hiding provider health problems.

Related Issues:

Solution

Extend the continuation-protection trusted outcome (introduced by #1517) with the first genuine upstream terminal error's code and status. The raw compaction finalization path now:

  1. Records failure when an upstream terminal error is present
  2. Suppresses successful-completion side effects (circuit breaker success, normal accounting)
  3. Releases request resources exactly once

Preserved behaviors: continuation-specific 400/409 handling, ordinary opaque HTTP responses, normal response diagnostics, and adapter-generated disconnect handling. The streamed HTTP response may already be 200; this change corrects only the final failure accounting.

Changes

Core Changes

  • src/app/v1/_lib/proxy/forwarder.ts (+229/-66) - Major rework: bind continuation requests to their upstream connection, prevent retry/migration for protected continuations, record terminal errors from upstream WebSocket events
  • src/app/v1/_lib/proxy/response-handler.ts (+49/-17) - Endpoint-level circuit isolation; respect trusted outcome for failure accounting in raw compaction finalization
  • src/app/v1/_lib/responses-ws/upstream-adapter.ts (+160/-33) - Track terminal error state from upstream error/response.failed events; expose outcome through trusted headers
  • src/app/v1/_lib/responses-ws/continuation.ts (new, +84) - Connection-local continuation binding: WeakMap-based session binding with provider, endpoint, generation, and header fingerprint verification
  • src/app/v1/_lib/proxy/error-handler.ts (+54) - Durable persistence of failure outcomes during raw compaction
  • src/app/v1/_lib/proxy/errors.ts (+12) - New ResponsesWsContinuationError for structured previous_response_not_found errors
  • src/app/v1/_lib/proxy/provider-selector.ts (+52/-9) - Session affinity awareness; selectProviderByType for continuation binding verification

Infrastructure Changes

  • server.js (+131/-37) - Exclusive /v1/responses upgrade handler installed before Next.js listeners; private HTTP bridge isolation; clean shutdown with close-handshake support
  • src/app/v1/_lib/responses-ws/internal-secret.ts (+6) - Internal trust header for connection-local WebSocket requests

Supporting Changes

  • src/app/v1/_lib/proxy/fake-streaming/proxy-integration.ts (+4) - Guard against fake streaming for WS continuations
  • src/app/v1/_lib/proxy/replay/replay-identity.ts (+3) - Guard against Replay for WS continuations
  • src/app/v1/_lib/proxy/stream-finalization.ts (+3) - One-time resource release guard
  • src/lib/utils/error-messages.ts (+1) - New error key RESPONSES_WS_PREVIOUS_RESPONSE_NOT_FOUND
  • messages/{en,ja,ru,zh-CN,zh-TW}/errors.json - i18n for the new error message (5 languages)

Series and Review

Part 3 of 3; depends on #1517, which depends on #1516. Keep this PR as a draft until its predecessors are merged and this branch is synchronized.

All three PRs target dev, so this branch initially includes all three commits. Merge order: #1516, #1517, then this PR.

Incremental review: a9adfb36.

Testing

Automated Tests (16 test files, 161+ new assertions)

New test files:

  • responses-ws/__tests__/continuation.test.ts - Continuation binding creation, verification, and rejection
  • responses-ws/__tests__/upstream-adapter.test.ts - Terminal error tracking from upstream events, outcome state propagation
  • server-ws-upgrade-routing.test.ts - Exclusive upgrade handler routing, listener ordering, delegation of non-WS paths
  • server-ws-continuation.test.ts - End-to-end connection-local continuation with binding validation
  • fake-streaming-ws-continuation.test.ts - Fake streaming guard for WS continuations
  • response-handler-endpoint-circuit-isolation.test.ts - Circuit breaker isolation respects failure outcomes

Extended test files:

  • error-handler-durable-persistence.test.ts - Raw compaction failure accounting with one-time resource release
  • proxy-forwarder-raw-passthrough-regression.test.ts - Retry prevention for bound continuations
  • proxy-forwarder-retry-limit.test.ts - Retry limit interaction with continuation binding
  • provider-selector-affinity-ignore-session.test.ts - Session affinity for continuation-bound requests
  • response-handler-stream-terminal.test.ts - Terminal error propagation through stream finalization
  • replay-identity.test.ts - Replay guard for WS continuations
  • server-ws-close-handshake.test.ts - Graceful close handshake during shutdown

Checklist

  • Code follows project conventions
  • i18n strings added for all 5 supported languages
  • No breaking changes to public API surface (new exports only)
  • Regression tests committed; full suite passed on the cumulative series tip
  • Series dependencies documented

Description enhanced by Claude AI

Publication validation

Production build, lint, lint auto-fix, typecheck, and full Vitest passed on the cumulative series tip in an isolated checkout (9,548 tests passed, 13 skipped). Every rewritten commit retains identical code, tests, translations, and configuration.

ROOOO added 3 commits October 18, 2026 10:23
Symptoms:
Responses WebSocket connections can close immediately after a successful
101 handshake, causing clients to report "Connection reset without closing
handshake" and repeatedly reconnect. Different worker initialization orders
can produce alternating successful and failed connections.

Cause:
CCH and Next.js can both handle the same WebSocket upgrade event. After CCH
completes the handshake, the Next.js listener can close the accepted socket.

Solution:
Route /v1/responses upgrades exclusively to CCH before invoking ordinary
upgrade listeners. Preserve listener dispatch for other paths, the current
worker's private HTTP loopback target, payload limits, and cleanup behavior.
Symptoms:
Responses WebSocket continuations can fail with previous_response_not_found
while the client connection remains open. Remote Compaction v2 can also
be recorded as successful after a structured WebSocket error.

Cause:
Logical session affinity does not guarantee reuse of the same physical
upstream WebSocket. Connection, routing, or credential changes can lose
connection-local history while requests still carry previous_response_id.
Structured WebSocket failures can also bypass final error accounting.

Solution:
Bind protected continuations to the live upstream connection, provider,
endpoint, generation, and complete request-header fingerprint.
Recheck access and limits, preserve prior storage semantics, and reject
invalid bindings with a canonical 400 error requiring full-context replay.
Prevent alternate routing, retries, HTTP fallback, hedging, Replay, and
fake streaming for protected continuations. Confirm terminal delivery
before closing, discard queued continuations, and preserve attempt-local
error accounting with idempotent resource cleanup.
Extend the trusted WebSocket outcome used by connection-local continuation
protection to genuine upstream terminal errors. Record raw compaction failures
and release attempt resources without successful completion side effects.

Preserve continuation-specific 400/409 handling, ordinary HTTP passthrough,
and normal response diagnostics.
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 01a4cf5d-f590-4196-be81-6259208d8e5f
📥 Commits

Reviewing files that changed from the base of the PR and between 8d6ddae and 72500b1.

📒 Files selected for processing: 35
  • docs/downstream-changes.md
  • messages/en/errors.json
  • messages/ja/errors.json
  • messages/ru/errors.json
  • messages/zh-CN/errors.json
  • messages/zh-TW/errors.json
  • server.js
  • src/app/v1/_lib/proxy/error-handler.ts
  • src/app/v1/_lib/proxy/errors.ts
  • src/app/v1/_lib/proxy/fake-streaming/proxy-integration.ts
  • src/app/v1/_lib/proxy/forwarder.ts
  • src/app/v1/_lib/proxy/provider-selector.ts
  • src/app/v1/_lib/proxy/replay/replay-identity.ts
  • src/app/v1/_lib/proxy/response-handler.ts
  • src/app/v1/_lib/proxy/stream-finalization.ts
  • src/app/v1/_lib/responses-ws/__tests__/continuation.test.ts
  • src/app/v1/_lib/responses-ws/__tests__/server-helpers.test.ts
  • src/app/v1/_lib/responses-ws/__tests__/upstream-adapter.test.ts
  • src/app/v1/_lib/responses-ws/continuation.ts
  • src/app/v1/_lib/responses-ws/internal-secret.ts
  • src/app/v1/_lib/responses-ws/upstream-adapter.ts
  • src/lib/utils/error-messages.ts
  • tests/unit/proxy/error-handler-durable-persistence.test.ts
  • tests/unit/proxy/fake-streaming-ws-continuation.test.ts
  • tests/unit/proxy/memory-aware-disk-timeout.test.ts
  • tests/unit/proxy/provider-selector-affinity-ignore-session.test.ts
  • tests/unit/proxy/provider-selector-select-provider-by-type.test.ts
  • tests/unit/proxy/proxy-forwarder-raw-passthrough-regression.test.ts
  • tests/unit/proxy/proxy-forwarder-retry-limit.test.ts
  • tests/unit/proxy/replay-identity.test.ts
  • tests/unit/proxy/response-handler-endpoint-circuit-isolation.test.ts
  • tests/unit/proxy/response-handler-stream-terminal.test.ts
  • tests/unit/server-ws-close-handshake.test.ts
  • tests/unit/server-ws-continuation.test.ts
  • tests/unit/server-ws-upgrade-routing.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.

📝 Walkthrough

此变更为 Responses WebSocket 增加升级路由和连接本地 continuation 处理。代理会校验上游连接绑定,并将可信 WebSocket 终止错误纳入响应结算。新增多语言错误消息、回归测试和下游变更记录。

Changes: Responses WebSocket continuation

Layer / File(s) Summary
升级路由与下游桥接
server.js, tests/unit/server-ws-*, src/app/v1/_lib/responses-ws/__tests__/server-helpers.test.ts, docs/downstream-changes.md
/v1/responses 升级由专用处理器处理,其他升级请求转交普通监听器。服务端在响应结束后检查本地绑定,并在 continuation 失效时关闭连接。
连接绑定与终止元数据
src/app/v1/_lib/responses-ws/continuation.ts, src/app/v1/_lib/responses-ws/internal-secret.ts, src/app/v1/_lib/responses-ws/upstream-adapter.ts, src/app/v1/_lib/responses-ws/__tests__/*
新增 connection-local 请求识别、会话绑定和响应 outcome。上游适配器校验 continuation 绑定,并记录可信终止错误的 code 与 status。
Provider 固定与代理路由限制
src/app/v1/_lib/proxy/provider-selector.ts, src/app/v1/_lib/proxy/forwarder.ts, src/app/v1/_lib/proxy/fake-streaming/*, src/app/v1/_lib/proxy/replay/*, tests/unit/proxy/*
Continuation 固定使用已绑定的 Provider、endpoint 和上游连接。失配时拒绝请求,不切换 Provider、不重试,也不回退到 HTTP;此类请求不进入 Replay 或 fake streaming。
错误响应与流结算
src/app/v1/_lib/proxy/error-handler.ts, src/app/v1/_lib/proxy/errors.ts, src/app/v1/_lib/proxy/response-handler.ts, src/app/v1/_lib/proxy/stream-finalization.ts, src/lib/utils/error-messages.ts, messages/*/errors.json, tests/unit/proxy/*, docs/downstream-changes.md
Continuation 错误返回结构化 400 响应。可信 WebSocket 终止错误参与流结算和诊断;对应路径不执行成功副作用,也不将 continuation 错误记为 Provider 健康失败。

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: ding113, tesgth032

Merge Risk: ⚪ Minimal · up to 72500

This change records genuine upstream WebSocket errors during raw compaction as failures and releases request resources once. No concrete merge-blocking defect was found. Merge only after the predecessor PRs land and the branch is synchronized, as the author states.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 38 functions across 29 files. (6 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed 标题准确概括了本次变更的主要目标,即修复 Responses WebSocket compaction 错误的记录和结算问题。
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed PR 描述明确说明了 Responses WebSocket 原始压缩路径中的上游错误统计问题,并对应描述了连接续接、错误结算、资源释放、测试和相关文件变更。描述与变更集相关。
Full details: Docstring Coverage

Explanation

Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 38 functions across 29 files. (6 skipped: 6 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ROOOO
ROOOO force-pushed the codex/ws-compaction-error-accounting branch from 72500b1 to a9adfb3 Compare October 22, 2026 08:31

This branch has not been deployed

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

Labels

area:core area:i18n bug Something isn't working

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant