Skip to content

[Bugfix] Clamp client-supplied remote_prefill_cached_tokens to the prompt length - #63659

Open
LeizhenZhang wants to merge 1 commit into
vllm-project:mainfrom
LeizhenZhang:fix/clamp-remote-cached-tokens
Open

LeizhenZhang wants to merge 1 commit into
vllm-project:mainfrom
LeizhenZhang:fix/clamp-remote-cached-tokens

Conversation

@LeizhenZhang

@LeizhenZhang LeizhenZhang commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Clamp the client-supplied kv_transfer_params.remote_prefill_cached_tokens override to [0, prompt_len] before it becomes num_cached_tokens. Fixes #58728.

This is the clamp @ptimizeroracle proposed in #58730, which robertgshaw2-redhat acked on the issue. That PR was closed by its author on 2026-10-23 for lack of review. I reproduced the bug independently on current main and am resubmitting the same approach with an end-to-end reproduction. Credit for the fix goes to @ptimizeroracle.

Claims

  • A client can no longer set usage.prompt_tokens_details.cached_tokens to an arbitrary or negative value through kv_transfer_params.
  • vllm:request_prefill_kv_computed_tokens no longer goes negative for such requests.

Validation

Reproducer on CPU through the real request path: JSON body, CompletionRequest.to_sampling_params, OutputProcessor, IterationStats. The prompt has 17 tokens and no local cache hits.

Client sends cached_tokens before kv_computed before cached_tokens after kv_computed after
9999 9999 -9982 17 0
-5 -5 17 0 17
3 3 14 3 14

New test, on the base commit and with the fix:

$ pytest -q tests/v1/engine/test_output_processor.py -k remote_prefill   # base
FAILED tests/v1/engine/test_output_processor.py::test_remote_prefill_cached_tokens_clamped_to_prompt_len[9999-8]
FAILED tests/v1/engine/test_output_processor.py::test_remote_prefill_cached_tokens_clamped_to_prompt_len[-5-0]
2 failed, 4 passed, 58 deselected
$ pytest -q tests/v1/engine/test_output_processor.py -k remote_prefill   # this PR
6 passed, 58 deselected

ruff check, ruff format --check (0.14.0, the pre-commit pin) and tools/pre_commit/mypy.py 3.11 vllm/v1/engine/output_processor.py pass. The test runs in the engine.yaml step (pytest -v -s v1/engine).

I could not run a RemoteOpenAIServer test here, because this machine's driver cannot run current main's CUDA 13 kernels. The reproducer above covers the same path below the engine core.

Details

kv_transfer_params is an ordinary request field on the completions, chat, responses and messages endpoints, and to_sampling_params forwards it with or without a KV connector. OutputProcessor copied remote_prefill_cached_tokens into num_cached_tokens with no bounds check. The clamp matches the bounds of the local count in PrefillStats. The Rust frontend change in #58885 reads the same field and may want the same bound.


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.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…ompt length

kv_transfer_params is a request field on the OpenAI-compatible endpoints,
so any client can set do_remote_prefill and remote_prefill_cached_tokens.
OutputProcessor copied that value into num_cached_tokens unchecked, which
let a request report cached_tokens larger than the prompt or negative in
usage.prompt_tokens_details and pushed negative observations into
vllm:request_prefill_kv_computed_tokens.

Keep the override within [0, prompt_len], the same bounds the local
count already has in PrefillStats.

Fixes vllm-project#58728

Signed-off-by: LeizhenZhang <zhangleizhen645@gmail.com>
@LeizhenZhang
LeizhenZhang requested a review from njhill as a code owner October 26, 2026 05:08

@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.

@mergify mergify Bot added the bug Something isn't working label Oct 26, 2026

@ptimizeroracle ptimizeroracle 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.

same change as #58730, thanks for picking it up and for the end-to-end table. lgtm

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

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: client-supplied kv_transfer_params.remote_prefill_cached_tokens can forge prompt_tokens_details.cached_tokens

2 participants