fix: detect and protect against truncated tool call output#2021
Merged
tanzhenxin merged 2 commits intoQwenLM:mainfrom Mar 2, 2026
Merged
fix: detect and protect against truncated tool call output#2021tanzhenxin merged 2 commits intoQwenLM:mainfrom
tanzhenxin merged 2 commits intoQwenLM:mainfrom
Conversation
When LLM streaming output exceeds token limits, JSON arguments for tool calls can be truncated mid-stream. This causes validation errors or silent data corruption when the truncated JSON passes validation but writes incomplete files. The fix adds truncation detection at the streaming parser level and overrides misleading finish_reason values from providers (e.g., DashScope/Qwen reporting 'stop' instead of 'length'). This ensures downstream code correctly identifies truncated responses and provides clear guidance to the LLM for retrying with split content. Changes: - turn.ts: Add wasOutputTruncated flag to ToolCallRequestInfo - coreToolScheduler.ts: Reject truncated edit tool calls, append guidance for write_file - converter.ts: Override finish_reason when streaming parser detects incomplete JSON - streamingToolCallParser.ts: Add hasIncompleteToolCalls() method - Tests: Add comprehensive test coverage for truncation detection scenarios Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This was referenced Mar 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: detect and protect against truncated tool call output
TLDR
When LLM output hits
max_tokens, tool call JSON gets truncated mid-stream. Some providers (DashScope/Qwen) misreportfinish_reason: "stop"instead of"length", making truncation invisible. This can silently write incomplete files to disk viawrite_file/edit.This PR detects incomplete JSON at the streaming parser level, overrides misleading
finish_reason, and rejectsKind.Edittool calls with recovery guidance.Dive Deeper
Problem
Two failure modes when tool call JSON is truncated:
jsonrepair"fixes" truncated JSON into valid-but-incomplete params —write_filewrites a half-finished file with no warning.Compounding this, some OpenAI-compatible providers report
finish_reason: "stop"even when output was cut off, so the existingMAX_TOKENScheck never fires.Solution
Four-layer defense chain:
streamingToolCallParser.ts—hasIncompleteToolCalls()checks JSON parsing state (depth > 0orinString) for structural completeness, independent of provider-reportedfinish_reason.converter.ts— Overridesfinish_reasonto"length"when the parser detects incomplete JSON but the provider reported"stop".turn.ts— StampswasOutputTruncated = trueon all pendingToolCallRequestInfowhenfinishReason === MAX_TOKENS.coreToolScheduler.ts— RejectsKind.Edittools outright withTRUNCATION_EDIT_REJECTION; appendsTRUNCATION_PARAM_GUIDANCEto any truncated param validation errors.Scope
Kind.Edit(write_file,edit) is rejected — non-edit tools fail safely at worst.content_block_stopevents (truncated calls are never emitted). Gemini SDK returns completePartobjects with reliablefinishReason.Files Changed
streamingToolCallParser.tshasIncompleteToolCalls()converter.tsfinish_reasonwhen incomplete JSON detectedturn.tswasOutputTruncatedflag toToolCallRequestInfocoreToolScheduler.tstool-error.tsToolErrorType.OUTPUT_TRUNCATED*.test.ts(3 files)Reviewer Test Plan
Automated
Manual
npm run buildmax_tokensor request a very large file write (e.g., "Write a 500-line React component to/tmp/test.tsx").Key Scenarios
write_filetruncated, provider reportsstopOUTPUT_TRUNCATEDwrite_filetruncated, provider reportslengthOUTPUT_TRUNCATEDwrite_filecomplete, normalstopedittruncatedOUTPUT_TRUNCATEDread_filetruncatedfinishReasonoverridden toMAX_TOKENSTesting Matrix
Linked issues / bugs