Skip to content

fix(sse): keep providerResponse in scope for failure usage (regression from #14544) - #14599

Merged
diegosouzapw merged 1 commit into
release/v3.8.51from
fix/chatcore-cpa-authindex-scope
Sep 23, 2026
Merged

diegosouzapw merged 1 commit into
release/v3.8.51from
fix/chatcore-cpa-authindex-scope

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Summary

Fixes a runtime regression that #14544 put on release/v3.8.51: every request whose upstream answers with a non-OK status made handleChatCore throw instead of returning the failure.

#14544 added cpaAuthIndex: readCpaAuthIndex(providerResponse) inside persistFailureUsage. That closure is declared near the top of handleChatCore (line ~688), but let providerResponse lived inside the large // prettier-ignore try { … } finally { … } body that opens at line 765 — so the name was not in the closure's scope. Because the try body is never re-indented (prettier-ignore), both lines sit at two spaces and look like the same scope; the TypeScript AST shows they are not (handleChatCore > Block@510 > ArrowFunction@688 vs handleChatCore > Block@510 > Block@765).

At runtime the argument object is built synchronously before saveRequestUsage is called, so ReferenceError: providerResponse is not defined is thrown from the closure. That try has no catch — only a finally that releases the turn — so the error escaped handleChatCore entirely. persistFailureUsage is called on 13 failure paths (429, upstream 4xx/5xx, model unavailable, context overflow, malformed translated response, stream readiness), so all of them were affected, and no failure usage was recorded.

Fix: move the let providerResponse; declaration out of the try to just before the closure. Net-zero lines (chatCore.ts stays at its 6402 ceiling). The try runs once per call — it is not a loop body — so hoisting does not change the variable's per-request lifetime, and there is no other providerResponse in the outer scope for it to collide with. readCpaAuthIndex already accepts unknown, so a failure before any upstream response exists reads as unattributed, exactly as #14544 intended.

Why CI did not catch it

typecheck:core does not cover open-sse/; the error only shows under check:open-sse-typecheck (chatCore.ts(706,40): error TS2304: Cannot find name 'providerResponse'). And no existing unit test drove a request through a path that reaches persistFailureUsage with the new field — until now.

Tests

  • New: tests/unit/chatcore-failure-usage-cpa-scope.test.ts — drives a real failure path end to end (upstream answers 400) and asserts handleChatCore resolves with success: false, status: 400 instead of rejecting. TDD: red on the tip with Got unwanted rejection … actual: ReferenceError: providerResponse is not defined, green with the fix. It also stands guard against the declaration ever being moved back inside the try.
  • Existing suites this restores, measured on the tip vs this branch:
suite tip this branch
chatcore-codex-account-pool 1 pass / 2 fail 3 / 0
chatcore-translation-paths 58 pass / 21 fail 75 / 4

The two codex-account-pool failures on the tip are literally ReferenceError: providerResponse is not defined. The 4 that remain in chatcore-translation-paths are a different, pre-existing failure — DeepSeek Responses reasoning replay and Codex Responses-native passthrough, AssertionError / database connection is not open, no providerResponse anywhere — already tracked in #14496, which predates #14544.

Validation (on this branch, after the commit)

check result
new test + chatcore-codex-account-pool + chatcore-failure-usage 9 pass / 0 fail
check:open-sse-typecheck the chatCore.ts TS2304 is gone; only the 8 pre-existing open-sse/executors/auggie.ts errors remain (TS2769 ×4, TS18047 ×4 — #14496, identical on the tip)
typecheck:core only the pre-existing src/lib/services/cliproxyAccountHealth.ts:157 TS2322 (host: options.host ?? externalHost, byte-identical on the tip)
check:file-size OK — chatCore.ts re-measured after the commit's Prettier pass: still 6402, exactly its ceiling
pre-commit hook lint-staged, docs-sync, any-budget, tracked-artifacts, ai-attribution — all passed

Refs #14544

#14544 made persistFailureUsage read providerResponse for the CPA auth
index, but the closure is declared before handleChatCore's large
prettier-ignore try block while `let providerResponse` lived inside it.
The name was out of scope, so every failure path threw
"ReferenceError: providerResponse is not defined" — and since that try
has only a finally, the error escaped handleChatCore instead of
returning the upstream failure.

Hoist the declaration above the closure. Net-zero lines; the try runs
once per call, so the per-request lifetime is unchanged.

Adds an end-to-end regression test that drives an upstream 400 through
handleChatCore: red on the tip with the ReferenceError, green here. The
fix also restores 2 failing tests in chatcore-codex-account-pool and 17
in chatcore-translation-paths that the same ReferenceError had broken.

Refs #14544
@diegosouzapw
diegosouzapw merged commit 99ba14b into release/v3.8.51 Sep 23, 2026
7 of 11 checks passed
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