Skip to content

fix(structured): report an output-limit stop instead of a JSON parse error - #94

Merged
senamakel merged 1 commit into
mainfrom
fix/structured-output-truncation-diagnostic
Aug 8, 2026
Merged

fix(structured): report an output-limit stop instead of a JSON parse error#94
senamakel merged 1 commit into
mainfrom
fix/structured-output-truncation-diagnostic

Conversation

@senamakel

@senamakel senamakel commented Aug 8, 2026

Copy link
Copy Markdown
Member

Summary

extract_provider_schema parses the response text without first checking whether there is any. When a reasoning model spends its whole output budget thinking and returns empty content, the error is:

schema 'tinysweeper_critique': response text is not valid JSON: expected value at line 1 column 1

That points at a malformed response which was never sent. The reader goes looking for bad JSON — the actual cause is truncation, and the fix is to raise max_tokens or cap reasoning.

How it was found

Reviewing a large pull request with moonshotai/kimi-k3 through OpenRouter. Calling the API directly with the same 49k-token prompt:

finish_reason     : length
completion_tokens : 8000      ← the entire budget
reasoning         : 17166 chars
content           : ""        ← nothing left for the answer

The provider had already said exactly what happened. ModelResponse::finish_reason carried it, and the extractor ignored it.

Worth noting for anyone hitting the same thing: OpenRouter's reasoning: {max_tokens: N} is ignored by this model — reasoning still grew past a 4096 cap. reasoning: {enabled: false} does work.

The change

Empty content is now reported as empty content. When finish_reason is length the message names the remedy; otherwise it reports the stop reason it did get. Genuinely malformed JSON still reports a parse error — there is a test pinning that, so the new branch cannot swallow the case it was not written for.

Tests

Three added in src/harness/structured/test.rs. cargo test --lib is green at 1405 passed; cargo clippy --all-targets -- -D warnings is clean.

Summary by CodeRabbit

  • Bug Fixes
    • Improved error messages when structured responses are empty because the output limit was reached.
    • Added a clear missing-content error for other empty responses.
    • Preserved accurate parsing errors for malformed JSON responses.

…error

A reasoning model can spend its entire output budget thinking and return no
content at all. The provider says so plainly through `finish_reason: "length"`,
but `extract_provider_schema` parsed the empty string regardless and surfaced

    schema 'x': response text is not valid JSON: expected value at line 1 column 1

which points at a malformed response that was never sent. The reader goes
looking for bad JSON; the actual fix is to raise `max_tokens` or cap reasoning.

Observed with `moonshotai/kimi-k3` on a 49k-token prompt: `finish_reason` was
`length`, `completion_tokens` was the full 8000, reasoning was 17k characters,
and content was empty.

Empty content is now reported as what it is, naming the remedy when the stop
reason confirms truncation, and reporting the stop reason otherwise. Genuinely
malformed JSON still reports a parse error.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5163b542-7da4-4489-8b38-8ac73e27f8ee

📥 Commits

Reviewing files that changed from the base of the PR and between 6655b6e and e1f8637.

📒 Files selected for processing (2)
  • src/harness/structured/mod.rs
  • src/harness/structured/test.rs

📝 Walkthrough

Walkthrough

The structured-output extractor now detects empty model responses before JSON parsing. It reports output-limit truncation separately from missing content. Tests cover both diagnostics and preserve parse errors for malformed non-empty JSON.

Changes

Structured output diagnostics

Layer / File(s) Summary
Empty response handling and validation
src/harness/structured/mod.rs, src/harness/structured/test.rs
extract_provider_schema reports a max_tokens error when finish_reason is "length" and a missing-content error otherwise. Tests cover both cases and retain malformed-JSON parse errors.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a rabbit with JSON in my paws,
Truncation now explains its cause.
Empty hops get errors clear,
Bad JSON keeps its parse-error cheer.
Carrots celebrate the fix! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: reporting output-limit stops instead of JSON parse errors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@senamakel
senamakel merged commit 1e6fd1a into main Aug 8, 2026
9 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