Skip to content

[#20991][fix] Poolside v1 tool parser: keep argument text that has no strict JSON form - #20992

Closed
LeizhenZhang wants to merge 1 commit into
NVIDIA:mainfrom
LeizhenZhang:fix/poolside-v1-argument-overflow
Closed

LeizhenZhang wants to merge 1 commit into
NVIDIA:mainfrom
LeizhenZhang:fix/poolside-v1-argument-overflow

Conversation

@LeizhenZhang

@LeizhenZhang LeizhenZhang commented Oct 26, 2026 •

Copy link
Copy Markdown

Dev Engineer Review

The parser retains raw argument text when a decoded value cannot be serialized as strict JSON. It also handles recursion and overflow errors during parsing. These changes target the linked issue’s reported failure cases. No current review findings or test execution results were supplied.

QA Engineer Review

tests/unittest/llmapi/apps/test_tool_parsers.py adds test_values_without_strict_json_keep_text for numeric overflow, non-finite values, and deeply nested arrays in one-shot and streaming modes. The test file is listed in tests/integration/test_lists/test-db/l0_cpu.yml. Coverage verdict: sufficient for the reported cases; test execution status is unavailable.

Per-File QA Perspective

  • tensorrt_llm/serve/tool_parser/poolside_v1_parser.py: Verify that unrepresentable values retain their raw text and that recursion or overflow errors do not escape one-shot or streaming parsing.
  • tests/unittest/llmapi/apps/test_tool_parsers.py: The added parameterized test covers the reported numeric, non-finite, and nested-array cases in both parsing modes. The file is listed in the CPU CI test list.

Description

Fixes #20991.

Problem

PoolsideV1ToolParser raises on some argument values the model can write.

value declared type main
1e999, Infinity, -Infinity integer OverflowError: cannot convert float infinity to integer
an integer with more than 308 digits number OverflowError: int too large to convert to float
100000 nested [ any non-string type RecursionError from json.loads
NaN, 1e999, [1e999] number, array the arguments string holds NaN or Infinity, which strict JSON parsers reject

The exception leaves both detect_and_parse and parse_streaming_increment. A non-streaming chat request then fails with HTTP 400 and the generated text is lost. A streaming request ends without its last chunks and without data: [DONE].

Root cause

_parse_argument_value in tensorrt_llm/serve/tool_parser/poolside_v1_parser.py:

  • json.loads(value) is guarded by (json.JSONDecodeError, ValueError), so RecursionError passes through.
  • int(parsed) and float(parsed) are guarded by (TypeError, ValueError). json.loads returns float("inf") for 1e999 and Infinity, int(inf) raises OverflowError, and so does float() of a very long integer.

Fix

_parse_argument_value keeps a decoded value only when json.dumps(..., allow_nan=False) can write it one level deep, which is the depth it has inside the arguments object. Otherwise it keeps the raw argument text. RecursionError from json.loads and OverflowError from the numeric conversions are caught. This is the rule glm4_parser.parse_arguments already applies to the same <arg_key>/<arg_value> format (1e309 and NaN keep their text there). Values that decode to strict JSON parse exactly as before.

The one-level-deep check matters at the decoder's nesting limit. On CPython 3.12 an array nested 9997 levels decodes, and then the json.dumps of the arguments object, one level deeper, raises RecursionError. A sweep of nesting depths from 1 to 3000 and 9980 to 10010 (arrays and objects, both parse paths) raises nothing after the change.

Test Coverage

New CPU-only test TestPoolsideV1ToolParser::test_values_without_strict_json_keep_text in tests/unittest/llmapi/apps/test_tool_parsers.py. It covers nine values (integer 1e999, -Infinity, NaN, number 1e999, NaN, 1.e999, a 400-digit integer, array [1e999], 100000 nested arrays) through detect_and_parse and parse_streaming_increment, and decodes the arguments with a parse_constant that rejects NaN and Infinity.

Results (CPU, tensorrt_llm 1.4.0rc1 wheel with the tool_parser package loaded from the checkout):

  • New test on main (687359e): 18 failed. Six raise OverflowError, two raise RecursionError, and ten return NaN or Infinity in the arguments string.
  • New test with the fix: 18 passed.
  • Whole test_tool_parsers.py on main: 896 passed, 4 failed.
  • Whole test_tool_parsers.py with the fix: 914 passed, 4 failed.

The same four tests fail on main and with the fix (TestQwen3CoderRequiredTools::test_required_stream_matches_complete_response[10000-True] and three TestQwen3CoderParameterRecovery::test_chat_recovery_policy_preserves_required_arguments cases). They go through postprocess_handlers and the reasoning parser, which this local setup takes from the 1.4.0rc1 wheel, so they come from the setup.

Open PR #19917 changes one line of _get_argument_type in the same file. The two changes touch different lines.

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

…has no strict JSON form

_parse_argument_value let three exceptions out of detect_and_parse and
parse_streaming_increment:

- OverflowError from int(parsed) when json.loads returns infinity
  (1e999, Infinity) for an integer argument
- OverflowError from float(parsed) for an integer with more than 308
  digits in a number argument
- RecursionError from json.loads on deeply nested arrays or objects

It also returned NaN and infinity, which json.dumps writes as NaN and
Infinity, so the arguments string was not valid JSON.

A decoded value is now kept only when json.dumps spells it as strict
JSON one level deep, the depth it has inside the arguments object.
Otherwise the raw argument text is kept, as glm4_parser.parse_arguments
already does for the same arg_key/arg_value format.

Signed-off-by: LeizhenZhang <zhangleizhen645@gmail.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between b7bfae8 and 15f60cc.

Files selected for processing: 2
  • tensorrt_llm/serve/tool_parser/poolside_v1_parser.py
  • tests/unittest/llmapi/apps/test_tool_parsers.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 8 remain after this review.

Walkthrough

The Poolside v1 parser now retains raw argument text when decoded values cannot be serialized as strict JSON. It also handles recursion and numeric conversion errors. Tests cover these cases in one-shot and streaming modes.

Changes

Poolside argument parsing

Layer / File(s) Summary
Strict JSON validation and fallback
tensorrt_llm/serve/tool_parser/poolside_v1_parser.py, tests/unittest/llmapi/apps/test_tool_parsers.py
The parser validates decoded and converted values as strict JSON. If validation or conversion fails, it retains the trimmed input text. Tests cover numeric overflow, non-finite values, oversized integers, and deeply nested arrays in one-shot and streaming modes.

Priority: Normal

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

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: Minimal · up to 15f60

No merge-blocking issue is established; the change is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description clearly explains the problem, root cause, fix, test coverage, known setup-related failures, and checklist status. It is complete and directly aligned with the pull request changes.
Title check Passed The title clearly summarizes the main change: retaining raw argument text when Poolside v1 tool values have no strict JSON representation.
Linked Issues check Passed Issue #20991 requires Poolside v1 parsing to return tool calls for numeric overflow, non-strict numeric values, and deeply nested values in both parsing paths. The change catches RecursionError and …
Out of Scope Changes check Passed The pull request changes only Poolside v1 argument parsing and its focused CPU-only tests. The helper and exception handling support the #20991 behavior, and the tests verify both required parsing pat…
Full details: Linked Issues check

Explanation

Issue #20991 requires Poolside v1 parsing to return tool calls for numeric overflow, non-strict numeric values, and deeply nested values in both parsing paths. The change catches RecursionError and OverflowError, validates decoded values with json.dumps(..., allow_nan=False), and retains raw text when strict JSON cannot represent the value. The new parameterized test covers nine values through detect_and_parse and parse_streaming_increment, including strict-JSON rejection of NaN and Infinity.

Full details: Out of Scope Changes check

Explanation

The pull request changes only Poolside v1 argument parsing and its focused CPU-only tests. The helper and exception handling support the #20991 behavior, and the tests verify both required parsing paths. No unrelated production behavior or unrelated test scope is introduced.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@LeizhenZhang

Copy link
Copy Markdown
Author

Following @karljang's review on #21005 to consolidate closely related changes, this Poolside v1 fix is now part of #20994 (commit 799aa51474). That PR handles undecodable tool-call arguments in the Kimi K3, MiniMax-M3, Poolside v1 and Gemma4 parsers, closes #20991, and keeps this PR's test. Closing this one in favour of #20994.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community want to contribute PRs initiated from Community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Poolside v1 tool parser raises on numeric arguments like 1e999 and on deeply nested JSON arguments

2 participants