Skip to content

[None][fix] validate reasoning item content in harmony responses input - #17738

Open
lonexreb wants to merge 3 commits into
NVIDIA:mainfrom
lonexreb:fix/responses-reasoning-content
Open

lonexreb wants to merge 3 commits into
NVIDIA:mainfrom
lonexreb:fix/responses-reasoning-content

Conversation

@lonexreb

@lonexreb lonexreb commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Description

The harmony path of _parse_response_input did content = input_msg["content"] plus a bare assert len(content) == 1 on unvalidated client input. Replaying a prior turn with a reasoning item that omits content — the canonical shape, since content is optional on reasoning items — raised KeyError: 'content', and an empty content list tripped the message-less assert, surfacing as an HTTP 400 with an empty error string.

Mirror the non-harmony sibling (_response_output_item_to_chat_completion_message): default missing content with .get(...) or [] and raise a descriptive ValueError.

Test Plan

  • POST /v1/responses on a harmony (gpt-oss) server with input: [{"type": "reasoning", "id": "rs_1", "summary": []}] now returns a 400 naming the reasoning item instead of KeyError/empty message.

Dev Engineer Review

  • _parse_response_input now treats missing or falsy reasoning content as an empty list, logs a debug message, and ignores the item.
  • The parser accepts one content element. It raises ValueError when more than one element is provided.
  • The missing-content behavior does not match the stated objective of raising a descriptive ValueError.
  • The diff also reformats code and docstrings in tensorrt_llm/serve/responses_utils.py.
  • git diff --check reported no whitespace errors. Test results are unavailable.

QA Engineer Review

No test changes.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: NVIDIA/TensorRT-LLM/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9848e657-58a5-4eb3-891f-be8be806830a

📥 Commits

Reviewing files that changed from the base of the PR and between f989376 and e47a848.

📒 Files selected for processing (1)
  • tensorrt_llm/serve/responses_utils.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tensorrt_llm/serve/responses_utils.py

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


Walkthrough

Reasoning input parsing ignores missing or falsy content, accepts one content element, and raises ValueError when multiple elements are provided.

Changes

Reasoning input validation

Layer / File(s) Summary
Content presence and cardinality validation
tensorrt_llm/serve/responses_utils.py
Missing or falsy content is ignored with debug logging. Multiple content elements raise ValueError. A single element still creates an assistant message.

Priority: ⬇️ Low

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

Change: Bug fix

Suggested reviewers: qijune

Merge Risk: ⚪ Minimal · up to e47a8

No actionable merge-blocking issue was identified in the reasoning-input change.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required [None][fix] format and clearly describes validation of reasoning item content in harmony responses input.
Description check ✅ Passed The description explains the issue, the proposed fix, and a relevant test plan. It omits the repository checklist, but the required technical content is mostly complete.
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

The harmony path of _parse_response_input indexed input_msg['content']
and asserted its length on unvalidated client input. Replaying a prior
turn with a reasoning item that omits 'content' (the canonical shape)
raised KeyError, and an empty list tripped a message-less assert that
surfaced as an HTTP 400 with an empty error string. Mirror the
non-harmony sibling: default missing content and raise a descriptive
ValueError.

Signed-off-by: lonexreb <reach2shubhankar@gmail.com>
@lonexreb
lonexreb force-pushed the fix/responses-reasoning-content branch from d87e29d to e212130 Compare August 17, 2026 02:13
assert len(content) == 1
content = input_msg.get("content") or []
if len(content) != 1:
raise ValueError(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you have stated, OpenAI Responses API allows reasoning "content" to be missing, and infers it from "id" or recovered from "encrypted_content".

Can you either

  • Make it clear in the error message that the support is unimplemented instead of the request being invalid
  • Follow the fallback standard behavior to ignore an empty reasoning message

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tongyuantongyu — went with the second option in f989376: a reasoning item with missing or empty content is now skipped (with a debug log noting that recovery from id/encrypted_content is unimplemented), matching the standard fallback behavior. The caller already filters None messages, so replayed turns parse cleanly. The descriptive error is kept only for the >1 content elements case.

The Responses API allows reasoning items without 'content' (inferred
from 'id' or recovered from 'encrypted_content', which is not
implemented here). Instead of rejecting such items as invalid, follow
the standard fallback behavior and skip them; the caller already
filters None messages.

Signed-off-by: lonexreb <reach2shubhankar@gmail.com>
@karljang

Copy link
Copy Markdown
Collaborator

It appears to be pre-commit check failures~, could you please take a look? Thank you!

Signed-off-by: lonexreb <reach2shubhankar@gmail.com>
@lonexreb

Copy link
Copy Markdown
Contributor Author

@karljang fixed in e47a848 — it was a yapf line-wrap on the new debug log; pre-commit now passes clean locally. Thanks for the heads-up!

@svc-trtllm-gh-bot svc-trtllm-gh-bot added the Community want to contribute PRs initiated from Community label Sep 27, 2026

This branch has not been deployed

No deployments
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.

4 participants