Skip to content

fix(sse): widen max_tokens/tool_use exemption to lone empty text blocks (#12968) - #13771

Merged
diegosouzapw merged 3 commits into
release/v3.8.51from
fix/12968-anthropic-shim-tiny-probe-empty
Sep 16, 2026
Merged

diegosouzapw merged 3 commits into
release/v3.8.51from
fix/12968-anthropic-shim-tiny-probe-empty

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Closes #12968

Root cause (short)

detectMalformedNonStream in open-sse/utils/diagnostics.ts only exempted a terminal stop_reason of max_tokens/tool_use (the #9971 fix) when content was a completely empty array (content: []). A tiny max_tokens probe against an Anthropic-compatible provider shim instead returns content: [{type:"text", text:""}] — one block with no visible text — which took a different path through the function and fell straight to empty_choices regardless of stop_reason, producing a false upstream_empty_response → 502. errorClassifier.ts's raw-body isEmptyContentResponse already handles this shape correctly (it short-circuits on content.length > 0), so the mismatch was only in the post-translation classifier.

Fix

Hoisted the stop_reason exemption check (max_tokens/tool_use) out of the content.length === 0 conditional so it applies whenever detectMalformedNonStream finds no visible output — regardless of whether content is [] or holds only textless/empty blocks. No change to errorClassifier.ts (already correct for this shape). The exemption's values (max_tokens, tool_use) are unchanged, only its scope test widened.

Regression test

tests/unit/issue-12968-anthropic-shim-empty-text-block.test.ts — built from the exact upstream body captured in the issue.

RED (unfixed code):

✖ #12968 max_tokens probe with content:[{text:''}] must NOT be flagged empty_choices (527ms)
  AssertionError [ERR_ASSERTION]: expected legitimate truncated-probe response to pass through, got reason=empty_choices
  + actual - expected
  + 'empty_choices'
  - null
✔ #12968 control — content:[] + max_tokens already exempted (#9971)
✔ #12968 control — empty text block with end_turn stop_reason stays flagged
tests 3, pass 2, fail 1

GREEN (fixed code):

✔ #12968 max_tokens probe with content:[{text:''}] must NOT be flagged empty_choices
✔ #12968 control — content:[] + max_tokens already exempted (#9971)
✔ #12968 control — empty text block with end_turn stop_reason stays flagged
tests 3, pass 3, fail 0

Gates run

  • npx eslint --suppressions-location config/quality/eslint-suppressions.json open-sse/utils/diagnostics.ts tests/unit/issue-12968-anthropic-shim-empty-text-block.test.ts → clean
  • npm run check:open-sse-typecheck → exit 0
  • node scripts/check/check-file-size.mjs → no violation on touched files (pre-existing open-sse/utils/stream.ts drift is base, not mine — identical line count on origin/release/v3.8.51)
  • node scripts/check/check-complexity.mjs → clean, no violations on touched files
  • node scripts/check/check-cognitive-complexity.mjs → OK, 1276 violations vs baseline 1437 (no regression)
  • node scripts/check/check-test-discovery.mjs → OK, new test file discovered
  • Existing suites re-run: tests/unit/diagnostics.test.ts, tests/unit/issue-9971-empty-choices-contentless-claude.test.ts, tests/unit/diagnostics-claude-thinking-5108.test.ts → 50/50 pass, no regressions

Existing tests aligned

None — no existing assertion encoded the old buggy contract; the new exemption scope is strictly additive to an already-correct set of cases (verified against all pre-existing Claude-shape tests in the files above).

diegosouzapw and others added 3 commits September 15, 2026 14:29
…ks (#12968)

detectMalformedNonStream (open-sse/utils/diagnostics.ts) only exempted a
terminal stop_reason of max_tokens/tool_use when content was a completely
empty array ([]). An Anthropic-compatible shim's tiny max_tokens:1 probe
instead returns content:[{type:"text",text:""}] — one block with no visible
text — which fell straight through to empty_choices regardless of
stop_reason, producing a false upstream_empty_response/502.

Fix hoists the stop_reason exemption check out of the content.length===0
conditional so it applies whenever detectMalformedNonStream finds no visible
output, matching errorClassifier.ts's existing raw-body behavior for the same
shape.

Regression test: tests/unit/issue-12968-anthropic-shim-empty-text-block.test.ts
@diegosouzapw
diegosouzapw merged commit 9578eeb into release/v3.8.51 Sep 16, 2026
19 of 21 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ks (diegosouzapw#12968) (diegosouzapw#13771)

Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
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.

fix(claude): Anthropic-compatible shim + tiny probe → 200/stop_reason=max_tokens + empty text misclassified as upstream_empty_response

1 participant