Skip to content

[Rust Frontend] Accept empty stream_options without streaming - #62643

Merged
BugenZhao merged 2 commits into
vllm-project:mainfrom
BugenZhao:bz/rust-parity-stream-options-empty
Oct 20, 2026
Merged

BugenZhao merged 2 commits into
vllm-project:mainfrom
BugenZhao:bz/rust-parity-stream-options-empty

Conversation

@BugenZhao

Copy link
Copy Markdown
Member

Overview

Python chat and completions reject stream_options without stream=true only when the object is non-empty (if data.get("stream_options") and not data.get("stream") in each validate_stream_options), and /inference/v1/generate has no such check. The Rust frontend rejects any stream_options with stream=false on all three routes, including {}. This PR aligns the Rust checks with Python.

Claims

  • Chat and completions accept "stream_options": {} without streaming and still reject a stream_options object that sets an option.
  • Non-streaming /inference/v1/generate accepts stream_options, as in Python; the non-streaming handler already ignores include_usage and continuous_usage_stats.
Request with stream=false Python Rust before Rust after
chat or completions, stream_options: {} 200 400 200
chat or completions, stream_options: {"include_usage": false} 400 400 400
generate, any stream_options 200 400 200

Validation

Commands from .buildkite/scripts/run-rust-frontend-cargo-ci.sh (style-clippy and test), run from the repo root:

cargo fmt --manifest-path rust/Cargo.toml --all -- --check   # ok
cargo sort --workspace --check rust                          # ok
cargo deny --manifest-path rust/Cargo.toml --config rust/deny.toml check bans   # ok
cargo clippy --manifest-path rust/Cargo.toml --workspace --all-targets --all-features --locked -- -D warnings   # ok
cargo nextest run --manifest-path rust/Cargo.toml --workspace --all-features --locked --no-fail-fast
# 2186 tests run: 2186 passed, 13 skipped
  • Chat and completions validate_request_compat_accepts_empty_stream_options_without_streaming ({}, through both chat layers) fail when the checks go back to stream_options.is_some().
  • Chat and completions validate_request_compat_rejects_stream_options_without_streaming cover {"include_usage": false} and {"continuous_usage_stats": true}.
  • Generate validate_request_compat_accepts_stream_options_without_streaming replaces the test that pinned the rejection.

Details

StreamOptions::is_empty sits on the shared DTO (routes/openai/utils/types.rs) and destructures every field, so a new option has to be considered there. Chat has two overlapping checks (the validate_chat_cross_parameters schema validator and validate_request_compat), and both change together; completions changes validate_request_compat. The generate check came from mirroring chat in #43779; Python's generate never had it, so it is removed rather than kept as a Rust-only rejection.

One edge case stays different: Python checks the raw JSON, so it rejects {"include_usage": null}; Rust sees the deserialized options and accepts it like {}.

Not a duplicate: the only open upstream PR touching stream_options and the Rust frontend area, #61275, adds a new Python option and does not change this validation.

AI assistance (Claude Code) was used to prepare this change; the human submitter reviewed every changed line.

🤖 Generated with Claude Code


Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

Python chat and completions reject `stream_options` without `stream=true`
only when the object is non-empty, and Python's generate route has no such
check. Rust rejected any `stream_options`, including `{}`, on all three.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@BugenZhao

Copy link
Copy Markdown
Member Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #96157 for commit c04ff8ceea9a.

ℹ️ This PR is 16 commits behind upstream main. Merged upstream main into this branch as c04ff8ceea9a before starting CI. Pull the branch before pushing more changes.

@BugenZhao
BugenZhao merged commit 68098c7 into vllm-project:main Oct 20, 2026
31 checks passed
bantianyue pushed a commit to bantianyue/vllm that referenced this pull request Oct 28, 2026
…roject#62643)

Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants