[Frontend] Migrate input-validation errors to VLLMValidationError (harmony/mistral/chat_utils/params) (#55735)
Signed-off-by: shaolila <shaolila@buaa.edu.cn> Co-authored-by: shaolila <shaolila@buaa.edu.cn>
Adababy committed
Sep 8, 2026 at 14:45 UTC
5133e1d28594d5939552003f32b55a3fb18556a1
7 files changed
+62
-8
tests/entrypoints/openai/test_render_parity.py
+14
@@ -29,6 +29,7 @@ from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionReque
29
from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
30
from vllm.entrypoints.openai.responses.serving import OpenAIServingResponses
31
from vllm.entrypoints.serve.engine.protocol import ErrorResponse
32
+from vllm.exceptions import VLLMValidationError
33
from vllm.inputs import tokens_input
34
from vllm.renderers.online_renderer import OnlineRenderer
35
from vllm.renderers.params import ChatParams
@@ -427,6 +428,19 @@ class TestReasoningRenderParity:
428
},
429
)
430
431
+ async def test_reasoning_effort_none_rejected_by_harmony(self, online_renderer):
432
+ """Harmony rejects reasoning_effort="none" as invalid user input."""
433
+ request = ChatCompletionRequest(
434
+ model=_MODEL,
435
+ messages=_USER,
436
+ reasoning_effort="none",
437
+ )
438
+ with pytest.raises(
439
+ VLLMValidationError, match="Harmony does not support"
440
+ ) as exc_info:
441
+ online_renderer._make_request_with_harmony(request)
442
+ assert exc_info.value.parameter == "reasoning_effort"
443
+
444
async def test_explicit_enable_thinking_not_overridden(
445
self, online_renderer, serving_responses
446
):
tests/entrypoints/unit_tests/test_chat_utils.py
+10
@@ -21,6 +21,7 @@ from vllm.entrypoints.chat_utils import (
21
_postprocess_messages,
22
parse_chat_messages,
23
parse_chat_messages_async,
24
+ validate_chat_template,
25
)
26
from vllm.exceptions import VLLMValidationError
27
from vllm.inputs import MultiModalDataDict, MultiModalUUIDDict
@@ -3138,3 +3139,12 @@ def test_tool_call_arguments_multiple_independent(caplog):
3139
3140
assert len(caplog.records) == 1
3141
assert "bad" in caplog.records[0].message
3142
+
3143
+
3144
+def test_validate_chat_template_rejects_invalid_type():
3145
+ """A non-str/Path chat_template is invalid user input."""
3146
+ with pytest.raises(
3147
+ VLLMValidationError, match="not a valid chat template type"
3148
+ ) as exc_info:
3149
+ validate_chat_template(123) # type: ignore[arg-type]
3150
+ assert exc_info.value.parameter == "chat_template"
tests/tokenizers_/test_mistral.py
+14
-1
@@ -11,6 +11,7 @@ from mistral_common.guidance.grammar_factory import GrammarFactory
11
from mistral_common.tokens.tokenizers.base import SpecialTokenPolicy, SpecialTokens
12
13
from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
14
+from vllm.exceptions import VLLMValidationError
15
from vllm.tokenizers.mistral import (
16
MistralTokenizer,
17
_validate_apply_chat_template_args,
@@ -2279,8 +2280,20 @@ def test_validate_request_params_rejects_unsupported_effort() -> None:
2280
messages=[],
2281
reasoning_effort="medium",
2282
)
2282
- with pytest.raises(ValueError, match="reasoning_effort"):
2283
+ with pytest.raises(VLLMValidationError, match="reasoning_effort") as exc_info:
2284
validate_request_params(request)
2285
+ assert exc_info.value.parameter == "reasoning_effort"
2286
+
2287
+
2288
+def test_validate_request_params_rejects_chat_template() -> None:
2289
+ request = ChatCompletionRequest(
2290
+ model="test-model",
2291
+ messages=[],
2292
+ chat_template="{{ messages }}",
2293
+ )
2294
+ with pytest.raises(VLLMValidationError, match="chat_template") as exc_info:
2295
+ validate_request_params(request)
2296
+ assert exc_info.value.parameter == "chat_template"
2297
2298
2299
# ---------------------------------------------------------------------------
vllm/entrypoints/chat_utils.py
+4
-1
@@ -1454,7 +1454,10 @@ def validate_chat_template(chat_template: Path | str | None):
1454
)
1455
1456
else:
1457
- raise TypeError(f"{type(chat_template)} is not a valid chat template type")
1457
+ raise VLLMValidationError(
1458
+ f"{type(chat_template)} is not a valid chat template type",
1459
+ parameter="chat_template",
1460
+ )
1461
1462
1463
def _load_chat_template(
vllm/renderers/online_renderer.py
+4
-1
@@ -512,7 +512,10 @@ class OnlineRenderer:
512
assert not self.supports_browsing
513
assert not self.supports_code_interpreter
514
if (reasoning_effort := request.reasoning_effort) == "none":
515
- raise ValueError(f"Harmony does not support {reasoning_effort=}")
515
+ raise VLLMValidationError(
516
+ f"Harmony does not support {reasoning_effort=}",
517
+ parameter="reasoning_effort",
518
+ )
519
tools = request.tools if should_include_tools else None
520
messages.extend(
521
build_harmony_preamble(
vllm/renderers/params.py
+8
-2
@@ -445,9 +445,15 @@ class TokenizeParams:
445
return tokens
446
447
if tokenizer is None:
448
- raise ValueError("Cannot pad tokens when `skip_tokenizer_init=True`")
448
+ raise VLLMValidationError(
449
+ "Cannot pad tokens when `skip_tokenizer_init=True`",
450
+ parameter="pad_prompt_tokens",
451
+ )
452
if not isinstance(tokens, list):
450
- raise ValueError("Cannot pad tokens for embedding inputs")
453
+ raise VLLMValidationError(
454
+ "Cannot pad tokens for embedding inputs",
455
+ parameter="pad_prompt_tokens",
456
+ )
457
458
return tokens + [tokenizer.pad_token_id] * (pad_length - len(tokens))
459
vllm/tokenizers/mistral.py
+8
-3
@@ -34,6 +34,7 @@ from transformers.tokenization_mistral_common import MistralCommonBackend
34
35
from vllm.entrypoints.chat_utils import ChatCompletionMessageParam
36
from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
37
+from vllm.exceptions import VLLMValidationError
38
from vllm.logger import init_logger
39
from vllm.tokenizers.protocol import TokenizerLike
40
@@ -144,15 +145,19 @@ def _validate_apply_chat_template_args(
145
146
def validate_request_params(request: "ChatCompletionRequest"):
147
if request.chat_template is not None or request.chat_template_kwargs is not None:
147
- raise ValueError("chat_template is not supported for Mistral tokenizers.")
148
+ raise VLLMValidationError(
149
+ "chat_template is not supported for Mistral tokenizers.",
150
+ parameter="chat_template",
151
+ )
152
153
if request.reasoning_effort and request.reasoning_effort not in list(
154
ReasoningEffort
155
):
152
- raise ValueError(
156
+ raise VLLMValidationError(
157
f"reasoning_effort={request.reasoning_effort} is not supported by "
158
"Mistral models. Supported values are: "
155
- f"{[e.value for e in ReasoningEffort]}."
159
+ f"{[e.value for e in ReasoningEffort]}.",
160
+ parameter="reasoning_effort",
161
)
162
163