main
py 183 lines 5.48 KB
Raw
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 http import HTTPStatus
7 from typing import Any
8
9
10 class VLLMError(Exception):
11 """Base class for all vLLM-specific errors.
12
13 Subclasses are split into `VLLMClientError` (caused by the request, mapped
14 to 4xx) and `VLLMServerError` (caused by the server, mapped to 5xx).
15 Dispatching on this hierarchy lets the entrypoints decide the HTTP status
16 without relying on raw Python exception types such as `ValueError`.
17 """
18
19
20 class VLLMClientError(VLLMError):
21 """Base class for errors caused by the client request (4xx)."""
22
23
24 class VLLMServerError(VLLMError):
25 """Base class for errors caused by the server (5xx)."""
26
27
28 class VLLMValidationError(VLLMClientError):
29 """vLLM-specific validation error for request validation failures.
30
31 Args:
32 message: The error message describing the validation failure.
33 parameter: Optional parameter name that failed validation.
34 value: Optional value that was rejected during validation.
35
36 """
37
38 def __init__(
39 self,
40 message: str,
41 *,
42 parameter: str | None = None,
43 value: Any = None,
44 ) -> None:
45 super().__init__(message)
46 self.parameter = parameter
47 self.value = value
48
49 def __str__(self):
50 base = super().__str__()
51 extras = []
52 if self.parameter is not None:
53 extras.append(f"parameter={self.parameter}")
54 if self.value is not None:
55 extras.append(f"value={self.value}")
56 return f"{base} ({', '.join(extras)})" if extras else base
57
58
59 class VLLMNotFoundError(VLLMClientError):
60 """vLLM-specific NotFoundError."""
61
62 pass
63
64
65 class LoRAAdapterNotFoundError(VLLMNotFoundError):
66 """Exception raised when a LoRA adapter is not found.
67
68 This exception is thrown when a requested LoRA adapter does not exist
69 in the system.
70
71 Attributes:
72 message: The error message string describing the exception
73
74 """
75
76 message: str
77
78 def __init__(
79 self,
80 lora_name: str,
81 lora_path: str,
82 ) -> None:
83 message = f"Loading lora {lora_name} failed: No adapter found for {lora_path}"
84 self.message = message
85
86 def __str__(self):
87 return self.message
88
89
90 class VLLMUnprocessableEntityError(VLLMClientError):
91 """vLLM-specific error for unprocessable entity requests.
92
93 This exception is raised when the request content is invalid or cannot be
94 processed, such as when an image URL points to a non-existent or inaccessible
95 resource (404, 403, DNS failure, etc.).
96
97 Args:
98 message: The error message describing the unprocessable entity.
99 parameter: Optional parameter name that failed validation.
100 value: Optional value that was rejected during validation.
101
102 """
103
104 def __init__(
105 self,
106 message: str,
107 *,
108 parameter: str | None = None,
109 value: Any = None,
110 ) -> None:
111 super().__init__(message)
112 self.parameter = parameter
113 self.value = value
114
115 def __str__(self):
116 base = super().__str__()
117 extras = []
118 if self.parameter is not None:
119 extras.append(f"parameter={self.parameter}")
120 if self.value is not None:
121 extras.append(f"value={self.value}")
122 return f"{base} ({', '.join(extras)})" if extras else base
123
124
125 class GenerationError(VLLMServerError):
126 """raised when finish_reason indicates internal server error (500)"""
127
128 def __init__(self, message: str = "Internal server error"):
129 super().__init__(message)
130 self.status_code = HTTPStatus.INTERNAL_SERVER_ERROR
131
132
133 class RetryableRequestError(GenerationError):
134 """A transient request-level failure that is safe for clients to retry."""
135
136 def __init__(self, message: str = "Request failed; please retry"):
137 super().__init__(message)
138 self.status_code = HTTPStatus.SERVICE_UNAVAILABLE
139
140
141 class GracefulHTTPError(VLLMError):
142 """Exception that should be translated into an HTTP error response.
143
144 These are expected to occur during normal operation (e.g. admission
145 control rejections) and should be surfaced to the client with the
146 explicit HTTP status code they carry, rather than being mapped to a
147 generic 4xx/5xx by the client/server split.
148 """
149
150 def __init__(self, message: str, http_status: HTTPStatus):
151 super().__init__(message)
152 self.message = message
153 self.http_status = http_status
154
155
156 class QueueOverflowError(GracefulHTTPError):
157 """Raised when admitting a request would exceed the request queue limit.
158
159 Returns HTTP 503 (Service Unavailable) so that load balancers and
160 client SDKs retry the request on a different instance.
161 """
162
163 def __init__(self):
164 super().__init__(
165 "The engine is currently busy and cannot accept new requests. "
166 "Please try again later or on a different instance.",
167 HTTPStatus.SERVICE_UNAVAILABLE,
168 )
169
170
171 class MaxQueuedTokensError(GracefulHTTPError):
172 """Raised when the pending prefill tokens exceed the configured limit.
173
174 Returns HTTP 503 (Service Unavailable) so that load balancers and
175 client SDKs retry the request on a different instance.
176 """
177
178 def __init__(self):
179 super().__init__(
180 "The engine has reached its prefill token backlog limit. "
181 "Please try again later or on a different instance.",
182 HTTPStatus.SERVICE_UNAVAILABLE,
183 )