Skip to content

fix(llm): carry usage and finish_reason on structured output failures - #256

Merged
wolfy-j merged 3 commits into
masterfrom
fix/llm-structured-failure-metadata
Nov 10, 2026
Merged

wolfy-j merged 3 commits into
masterfrom
fix/llm-structured-failure-metadata

Conversation

@wolfy-j

@wolfy-j wolfy-j commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Structured-output failures after a provider reply lose the reply's usage and finish reason. This change adds details.tokens and normalized details.finish_reason to those errors and records the reported tokens and finish reason through the existing rejected-usage tracker. Failures without a provider reply add neither field. Error metadata extraction validates provider field types and omits unusable fields. Google retains its existing protected response-mapping boundary.

All five providers preserve their existing success/failure outcomes, error kinds, retryability, exact messages and existing details. Parseable JSON or tool input with a length stop reason retains its existing behavior, including Claude native structured mode's existing rejection. Existing error details and caller metadata retain precedence when a key already exists. The README explains detecting truncation through details.finish_reason == "length".

Validation uses runtime v0.3.59a and refreshed dependencies:

  • Per-driver contract matrix: 94 cases match origin/master for outcomes, exact messages, kinds, retryability and existing details. Additive metadata checks cover all five providers, malformed usage and finish-reason fields, nested usage details, malformed Google envelopes and transport failures. Success cases also compare tokens, finish reason and metadata with the base branch.
  • LLM suite: 2,905 passing tests, 9 existing credential-dependent skips; LLM lint passes (143 entries).
  • Agent suite against the changed LLM: 641 passing tests on SQLite and PostgreSQL, 4 existing integration skips per run; agent lint passes (141 entries).
  • Regression tests cover existing detail fields, reusable builders, caller metadata and failure-then-success accounting without double counting. Module manifest validation passes.

KickSide added 3 commits November 10, 2026 15:55
A structured output call that failed after the provider answered (a reply
cut by the output limit, a refusal, a reply that is not JSON, a missing
tool call) dropped the reply's usage and finish reason. A truncated reply
surfaced as invalid JSON, and its tokens were not recorded.

The error builder takes the received response's usage and finish reason,
and every error built afterwards carries them in details.tokens and
details.finish_reason. Each structured output driver reports a reply cut
by the output limit as model_error with finish_reason length before
decoding it. A failure without a provider reply carries no tokens. The
rejected usage record holds the failed reply's tokens and finish reason.
@wolfy-j
wolfy-j merged commit 91957e2 into master Nov 10, 2026
25 checks passed
@wolfy-j
wolfy-j deleted the fix/llm-structured-failure-metadata branch November 10, 2026 21:54
@wippy-releases wippy-releases Bot mentioned this pull request Nov 10, 2026
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