[Bugfix] Reject empty bad-word tokenizations (#53433)

Signed-off-by: Andreas Karatzas <akaratza@amd.com>

Andreas Karatzas committed Aug 31, 2026 at 12:07 UTC a9dc631429bec8709afa993595d91e27b00cabe6
2 files changed +45
tests/test_request_input_bounds.py
+34
@@ -162,6 +162,40 @@ def test_bad_word_tokenization_limit_can_be_overridden(monkeypatch):
162 assert tokenizer.calls == 3
163
164
165 +class EmptyBaseEncodingTokenizer:
166 + max_token_id = 1024
167 +
168 + def encode(self, text: str, add_special_tokens: bool = False) -> list[int]:
169 + return [216] if text.startswith(" ") else []
170 +
171 +
172 +def test_bad_word_rejects_empty_base_tokenization():
173 + params = SamplingParams(bad_words=["\x16"])
174 +
175 + with pytest.raises(
176 + VLLMValidationError,
177 + match="must tokenize to at least one token",
178 + ) as exc_info:
179 + params.update_from_tokenizer(EmptyBaseEncodingTokenizer())
180 +
181 + assert exc_info.value.parameter == "bad_words"
182 +
183 +
184 +class EmptyPrefixedEncodingTokenizer:
185 + max_token_id = 1024
186 +
187 + def encode(self, text: str, add_special_tokens: bool = False) -> list[int]:
188 + return [] if text.startswith(" ") else [321]
189 +
190 +
191 +def test_bad_word_skips_empty_optional_prefixed_tokenization():
192 + params = SamplingParams(bad_words=["word"])
193 +
194 + params.update_from_tokenizer(EmptyPrefixedEncodingTokenizer())
195 +
196 + assert params.bad_words_token_ids == [[321]]
197 +
198 +
199 # --- Beam search: beam width / n honor the sequence cap --------------------
200
201
vllm/sampling_params.py
+11
@@ -707,6 +707,17 @@ class SamplingParams(
707 text=prompt, add_special_tokens=False
708 )
709
710 + if not prompt_token_ids:
711 + if not add_prefix_space:
712 + raise VLLMValidationError(
713 + "bad_words entries must tokenize to at least one token.",
714 + parameter="bad_words",
715 + value=self.bad_words,
716 + )
717 + # The unprefixed form is still enforceable when only the
718 + # optional space-prefixed form tokenizes to nothing.
719 + continue
720 +
721 # If no space at the beginning
722 # or if prefix space produces a new word token
723 if (not add_prefix_space) or (