[Bug]: System crash: Rust frontend aborts the process on prompt logprobs for a zero-token prompt
bug
### Your current environment
`vllm/collect_env.py` output is not included: this reproduces entirely against the Rust workspace under `rust/`, driven by `cargo run` and no engine at all. The vLLM Python package is not installed on the repro machine and there is no GPU, so `collect_env.py` would report `N/A` for essentially every field it exists to collect. Nothing in the affected code path touches torch, CUDA, or the Python runtime. Happy to provide a full dump from a GPU install if that is needed for triage.
```
vLLM commit e2fa28594f7baad142a426b0b6a2cfe2c79201c7 (2026-08-02)
Toolchain rustc 1.95.0 (59807616e 2026-04-14) <- pinned by rust-toolchain.toml
OS Ubuntu 26.04 LTS, Linux 7.0.0-27-generic, x86_64
```
<details>
<summary>The output of <code>python collect_env.py</code></summary>
```text
Your output of `python collect_env.py` here
```
</details>
### 🐛 Describe the bug
`decode_prompt_logprobs` assumes the prompt has at least one token and enforces that with `.expect()`. If prompt logprobs arrive for a zero-token prompt, the Rust frontend panics, and because the workspace sets `panic = "abort"` in the release profile, the process aborts rather than the request failing.
The panic cannot be contained by catch_unwind or a tower CatchPanicLayer, the process terminates, taking every other in-flight request on that server with it. A single request that reaches this line is a full outage until the server is restarted.
```rust
// rust/src/text/src/output/logprobs.rs:89
let first_token_id = prompt_token_ids
.first()
.copied()
.expect("prompt logprobs require at least one prompt token");
```
- **Component:** `rust/src/text/src/output/logprobs.rs:89`
- **Reached from:** `decoded_text_event_stream` when the first engine output carries `prompt_info` with prompt logprobs and empty `prompt_token_ids`.
- **Found by:** fuzzing `decoded_text_event_stream` with request-controlled decode options.
## Reproduction
Single self-contained repro script :
[empty_prompt_logprobs.rs](https://gist.github.com/Yunzez/51d4a8a4bdd1c76140f418f870492010)
```bash
mkdir -p rust/src/text/examples
cp empty_prompt_logprobs.rs rust/src/text/examples/
cd rust
cargo run --release -p vllm-text --example empty_prompt_logprobs
```
```
[control] prompt of 1 token(s) + prompt logprobs ...
[control] -> Ok
[empty prompt] prompt of 0 token(s) + prompt logprobs ...
thread 'main' panicked at src/text/src/output/logprobs.rs:89:10:
prompt logprobs require at least one prompt token
```
Only the prompt length differs between the two cases. The control runs first so its success is visible even though the second case aborts.
The Python side *does* have this check `vllm/v1/engine/input_processor.py:405`:
```python
if prompt_len == 0 and prompt_type == "decoder":
raise VLLMValidationError(f"The {prompt_type} prompt cannot be empty")
```
but `InputProcessor` is constructed and driven by `AsyncLLM` (`vllm/v1/engine/async_llm.py:138`), the component the Rust frontend replaces. `core.py` neither imports nor calls it.
## Suggested fix
- Simply return an error instead of `.expect()` in `decode_prompt_logprobs`, the caller already propagates `Result`, so a decode error surfaces as a failed request rather than an abort.
- Or maybe better, we can reject earlier: extend `TextRequest::validate` to cover the *tokenized* prompt (or add an emptiness check after tokenization in `lower_text_request`), so an empty prompt fails with a clear 400.
### Before submitting a new issue...
- [x] Make sure you already searched for relevant issues, and asked the chatbot living at the bottom right corner of the [documentation page](https://docs.vllm.ai/en/latest/), which can answer lots of frequently asked questions.
0 条评论