A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 10, 14:00 UTC
[OpenAI] Extend VLLMValidationError to additional validation parameters (#31870)
Signed-off-by: Rehan Khan <Rehan.Khan7@ibm.com>
R3hankhan committed
Jan 7, 2026 at 20:15 UTC
1ab055efe6b7f9abdd8774ed64ead1b83dd00253
9 files changed
+89
-56
vllm/entrypoints/openai/api_server.py
+1
-1
@@ -911,7 +911,7 @@ def build_app(args: Namespace) -> FastAPI:
911
912
@app.exception_handler(RequestValidationError)
913
async def validation_exception_handler(_: Request, exc: RequestValidationError):
914
- from vllm.entrypoints.openai.protocol import VLLMValidationError
914
+ from vllm.exceptions import VLLMValidationError
915
916
param = None
917
for error in exc.errors():
vllm/entrypoints/openai/protocol.py
+1
-30
@@ -72,6 +72,7 @@ from pydantic import (
72
)
73
74
from vllm.entrypoints.chat_utils import ChatCompletionMessageParam, make_tool_call_id
75
+from vllm.exceptions import VLLMValidationError
76
from vllm.logger import init_logger
77
from vllm.logprobs import Logprob
78
from vllm.sampling_params import (
@@ -131,36 +132,6 @@ class ErrorResponse(OpenAIBaseModel):
132
error: ErrorInfo
133
134
134
-class VLLMValidationError(ValueError):
135
- """vLLM-specific validation error for request validation failures.
136
-
137
- Args:
138
- message: The error message describing the validation failure.
139
- parameter: Optional parameter name that failed validation.
140
- value: Optional value that was rejected during validation.
141
- """
142
-
143
- def __init__(
144
- self,
145
- message: str,
146
- *,
147
- parameter: str | None = None,
148
- value: Any = None,
149
- ) -> None:
150
- super().__init__(message)
151
- self.parameter = parameter
152
- self.value = value
153
-
154
- def __str__(self):
155
- base = super().__str__()
156
- extras = []
157
- if self.parameter is not None:
158
- extras.append(f"parameter={self.parameter}")
159
- if self.value is not None:
160
- extras.append(f"value={self.value}")
161
- return f"{base} ({', '.join(extras)})" if extras else base
162
-
163
-
135
class ModelPermission(OpenAIBaseModel):
136
id: str = Field(default_factory=lambda: f"modelperm-{random_uuid()}")
137
object: str = "model_permission"
vllm/entrypoints/openai/serving_completion.py
+4
-4
@@ -140,16 +140,16 @@ class OpenAIServingCompletion(OpenAIServing):
140
)
141
except ValueError as e:
142
logger.exception("Error in preprocessing prompt inputs")
143
- return self.create_error_response(str(e))
143
+ return self.create_error_response(e)
144
except TypeError as e:
145
logger.exception("Error in preprocessing prompt inputs")
146
- return self.create_error_response(str(e))
146
+ return self.create_error_response(e)
147
except RuntimeError as e:
148
logger.exception("Error in preprocessing prompt inputs")
149
- return self.create_error_response(str(e))
149
+ return self.create_error_response(e)
150
except jinja2.TemplateError as e:
151
logger.exception("Error in preprocessing prompt inputs")
152
- return self.create_error_response(str(e))
152
+ return self.create_error_response(e)
153
154
# Extract data_parallel_rank from header (router can inject it)
155
data_parallel_rank = self._get_data_parallel_rank(raw_request)
vllm/entrypoints/openai/serving_engine.py
+1
-1
@@ -754,7 +754,7 @@ class OpenAIServing:
754
if isinstance(message, Exception):
755
exc = message
756
757
- from vllm.entrypoints.openai.protocol import VLLMValidationError
757
+ from vllm.exceptions import VLLMValidationError
758
759
if isinstance(exc, VLLMValidationError):
760
err_type = "BadRequestError"
vllm/entrypoints/openai/serving_responses.py
+1
-1
@@ -373,7 +373,7 @@ class OpenAIServingResponses(OpenAIServing):
373
NotImplementedError,
374
) as e:
375
logger.exception("Error in preprocessing prompt inputs")
376
- return self.create_error_response(f"{e} {e.__cause__}")
376
+ return self.create_error_response(e)
377
378
request_metadata = RequestResponseMetadata(request_id=request.request_id)
379
if raw_request:
vllm/entrypoints/renderer.py
+1
-1
@@ -12,7 +12,7 @@ import torch
12
from pydantic import Field
13
14
from vllm.config import ModelConfig
15
-from vllm.entrypoints.openai.protocol import VLLMValidationError
15
+from vllm.exceptions import VLLMValidationError
16
from vllm.inputs.data import EmbedsPrompt, TextPrompt, TokensPrompt
17
from vllm.inputs.parse import get_prompt_components, parse_raw_prompts
18
from vllm.tokenizers import TokenizerLike
vllm/exceptions.py
new
+36
@@ -0,0 +1,36 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+
4
+"""Custom exceptions for vLLM."""
5
+
6
+from typing import Any
7
+
8
+
9
+class VLLMValidationError(ValueError):
10
+ """vLLM-specific validation error for request validation failures.
11
+
12
+ Args:
13
+ message: The error message describing the validation failure.
14
+ parameter: Optional parameter name that failed validation.
15
+ value: Optional value that was rejected during validation.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ message: str,
21
+ *,
22
+ parameter: str | None = None,
23
+ value: Any = None,
24
+ ) -> None:
25
+ super().__init__(message)
26
+ self.parameter = parameter
27
+ self.value = value
28
+
29
+ def __str__(self):
30
+ base = super().__str__()
31
+ extras = []
32
+ if self.parameter is not None:
33
+ extras.append(f"parameter={self.parameter}")
34
+ if self.value is not None:
35
+ extras.append(f"value={self.value}")
36
+ return f"{base} ({', '.join(extras)})" if extras else base
vllm/sampling_params.py
+31
-12
@@ -11,6 +11,7 @@ from typing import Annotated, Any
11
import msgspec
12
from pydantic.dataclasses import dataclass
13
14
+from vllm.exceptions import VLLMValidationError
15
from vllm.logger import init_logger
16
from vllm.logits_process import LogitsProcessor
17
from vllm.tokenizers import TokenizerLike
@@ -393,11 +394,17 @@ class SamplingParams(
394
f"{self.repetition_penalty}."
395
)
396
if self.temperature < 0.0:
396
- raise ValueError(
397
- f"temperature must be non-negative, got {self.temperature}."
397
+ raise VLLMValidationError(
398
+ f"temperature must be non-negative, got {self.temperature}.",
399
+ parameter="temperature",
400
+ value=self.temperature,
401
)
402
if not 0.0 < self.top_p <= 1.0:
400
- raise ValueError(f"top_p must be in (0, 1], got {self.top_p}.")
403
+ raise VLLMValidationError(
404
+ f"top_p must be in (0, 1], got {self.top_p}.",
405
+ parameter="top_p",
406
+ value=self.top_p,
407
+ )
408
# quietly accept -1 as disabled, but prefer 0
409
if self.top_k < -1:
410
raise ValueError(
@@ -410,7 +417,11 @@ class SamplingParams(
417
if not 0.0 <= self.min_p <= 1.0:
418
raise ValueError(f"min_p must be in [0, 1], got {self.min_p}.")
419
if self.max_tokens is not None and self.max_tokens < 1:
413
- raise ValueError(f"max_tokens must be at least 1, got {self.max_tokens}.")
420
+ raise VLLMValidationError(
421
+ f"max_tokens must be at least 1, got {self.max_tokens}.",
422
+ parameter="max_tokens",
423
+ value=self.max_tokens,
424
+ )
425
if self.min_tokens < 0:
426
raise ValueError(
427
f"min_tokens must be greater than or equal to 0, got {self.min_tokens}."
@@ -421,24 +432,30 @@ class SamplingParams(
432
f"max_tokens={self.max_tokens}, got {self.min_tokens}."
433
)
434
if self.logprobs is not None and self.logprobs != -1 and self.logprobs < 0:
424
- raise ValueError(
425
- f"logprobs must be non-negative or -1, got {self.logprobs}."
435
+ raise VLLMValidationError(
436
+ f"logprobs must be non-negative or -1, got {self.logprobs}.",
437
+ parameter="logprobs",
438
+ value=self.logprobs,
439
)
440
if (
441
self.prompt_logprobs is not None
442
and self.prompt_logprobs != -1
443
and self.prompt_logprobs < 0
444
):
432
- raise ValueError(
445
+ raise VLLMValidationError(
446
f"prompt_logprobs must be non-negative or -1, got "
434
- f"{self.prompt_logprobs}."
447
+ f"{self.prompt_logprobs}.",
448
+ parameter="prompt_logprobs",
449
+ value=self.prompt_logprobs,
450
)
451
if self.truncate_prompt_tokens is not None and (
452
self.truncate_prompt_tokens == 0 or self.truncate_prompt_tokens < -1
453
):
439
- raise ValueError(
454
+ raise VLLMValidationError(
455
f"truncate_prompt_tokens must be an integer >= 1 or -1, "
441
- f"got {self.truncate_prompt_tokens}"
456
+ f"got {self.truncate_prompt_tokens}",
457
+ parameter="truncate_prompt_tokens",
458
+ value=self.truncate_prompt_tokens,
459
)
460
assert isinstance(self.stop_token_ids, list)
461
if not all(isinstance(st_id, int) for st_id in self.stop_token_ids):
@@ -516,12 +533,14 @@ class SamplingParams(
533
if token_id < 0 or token_id > tokenizer.max_token_id
534
]
535
if len(invalid_token_ids) > 0:
519
- raise ValueError(
536
+ raise VLLMValidationError(
537
f"The model vocabulary size is {tokenizer.max_token_id + 1},"
538
f" but the following tokens"
539
f" were specified as bad: {invalid_token_ids}."
540
f" All token id values should be integers satisfying:"
524
- f" 0 <= token_id <= {tokenizer.max_token_id}."
541
+ f" 0 <= token_id <= {tokenizer.max_token_id}.",
542
+ parameter="bad_words",
543
+ value=self.bad_words,
544
)
545
546
@cached_property
vllm/v1/engine/input_processor.py
+13
-6
@@ -6,6 +6,7 @@ from collections.abc import Mapping
6
from typing import Any, Literal, cast
7
8
from vllm.config import VllmConfig
9
+from vllm.exceptions import VLLMValidationError
10
from vllm.inputs import ProcessorInputs, PromptType, SingletonInputs
11
from vllm.inputs.parse import split_enc_dec_inputs
12
from vllm.inputs.preprocess import InputPreprocessor
@@ -83,9 +84,11 @@ class InputProcessor:
84
if num_logprobs == -1:
85
num_logprobs = self.model_config.get_vocab_size()
86
if num_logprobs > max_logprobs:
86
- raise ValueError(
87
+ raise VLLMValidationError(
88
f"Requested sample logprobs of {num_logprobs}, "
88
- f"which is greater than max allowed: {max_logprobs}"
89
+ f"which is greater than max allowed: {max_logprobs}",
90
+ parameter="logprobs",
91
+ value=num_logprobs,
92
)
93
94
# Validate prompt logprobs.
@@ -94,9 +97,11 @@ class InputProcessor:
97
if num_prompt_logprobs == -1:
98
num_prompt_logprobs = self.model_config.get_vocab_size()
99
if num_prompt_logprobs > max_logprobs:
97
- raise ValueError(
100
+ raise VLLMValidationError(
101
f"Requested prompt logprobs of {num_prompt_logprobs}, "
99
- f"which is greater than max allowed: {max_logprobs}"
102
+ f"which is greater than max allowed: {max_logprobs}",
103
+ parameter="prompt_logprobs",
104
+ value=num_prompt_logprobs,
105
)
106
107
def _validate_sampling_params(
@@ -134,9 +139,11 @@ class InputProcessor:
139
invalid_token_ids.append(token_id)
140
141
if invalid_token_ids:
137
- raise ValueError(
142
+ raise VLLMValidationError(
143
f"token_id(s) {invalid_token_ids} in logit_bias contain "
139
- f"out-of-vocab token ids. Vocabulary size: {vocab_size}"
144
+ f"out-of-vocab token ids. Vocabulary size: {vocab_size}",
145
+ parameter="logit_bias",
146
+ value=invalid_token_ids,
147
)
148
149
def _validate_supported_sampling_params(