[Bugfix][Frontend] Return 4xx for client errors in /cohere/v2/chat (#60309)

Signed-off-by: sricursion <sricursion@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Sriraj
2026-10-07 04:55:34 +00:00
committed by GitHub
co-authored by Claude
parent aecb717f10
commit 43b4aaea3e
2 changed files with 29 additions and 22 deletions
+22 -6
View File
@@ -50,7 +50,7 @@ from vllm.entrypoints.serve.exception_handling.handlers.validation import (
from vllm.entrypoints.serve.exception_handling.handlers.vllm_error import (
vllm_error_handler,
)
from vllm.exceptions import VLLMError
from vllm.exceptions import VLLMError, VLLMValidationError
from vllm.sampling_params import SamplingParams
@@ -78,7 +78,7 @@ class _Handler:
* a :class:`CohereChatV2Response` (non-streaming JSON path);
* an async generator yielding SSE frames (streaming path);
* an :class:`ErrorResponse` (error envelope path); or
* an exception (router-level 500 path).
* an exception (router-level error path).
"""
def __init__(self, result):
@@ -371,6 +371,22 @@ class TestEndpoint:
body = r.json()
assert body == {"message": "kaboom"}
@pytest.mark.parametrize(
"exc",
[
VLLMValidationError("bad temperature", parameter="temperature"),
ValueError("bad temperature"),
],
ids=["vllm_validation_error", "value_error"],
)
def test_handler_client_error_returns_400_envelope(self, exc):
"""Client-caused handler errors are 4xx, matching the OpenAI routes."""
app = _build_app(handler=_Handler(exc))
with TestClient(app) as client:
r = client.post("/cohere/v2/chat", json=_minimal_request_body())
assert r.status_code == HTTPStatus.BAD_REQUEST
assert "bad temperature" in r.json()["message"]
def test_non_json_content_type_rejected(self):
"""The ``validate_json_request`` dependency raises
``RequestValidationError`` (HTTP 422) for non-JSON content
@@ -525,10 +541,10 @@ class TestRenderEndpoint:
assert r.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
assert r.json() == {"message": "tokenizer exploded"}
def test_conversion_exception_returns_500_envelope(self):
def test_conversion_client_error_returns_400_envelope(self):
"""Conversion runs inside the same ``try`` as the render call, so
a bad v2 body that slips past Pydantic still yields the Cohere
error envelope rather than an unhandled 500 with vLLM's shape.
a bad v2 body that slips past Pydantic still yields a 4xx in the
Cohere error envelope rather than an unhandled 500 with vLLM's shape.
"""
class _Boom:
@@ -538,7 +554,7 @@ class TestRenderEndpoint:
app = _build_render_app(_Boom(), _RenderHandler(_generate_request()))
with TestClient(app) as client:
r = client.post("/cohere/v2/chat/render", json=_minimal_request_body())
assert r.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
assert r.status_code == HTTPStatus.BAD_REQUEST
assert r.json() == {"message": "unconvertible message"}
def test_invalid_body_returns_422(self):
+7 -16
View File
@@ -40,6 +40,9 @@ from starlette.middleware.base import BaseHTTPMiddleware
import vllm.envs as envs
from vllm.entrypoints.serve.engine.protocol import ErrorResponse
from vllm.entrypoints.serve.exception_handling.error_response import (
create_error_response,
)
from vllm.entrypoints.serve.exception_handling.utils import sanitize_message
from vllm.entrypoints.serve.utils.api_utils import (
load_aware_call,
@@ -138,15 +141,9 @@ if _SDK_AVAILABLE:
try:
result = await handler.create_chat_v2(request, raw_request)
except Exception as e: # noqa: BLE001 - report as 500 for parity
except Exception as e:
logger.exception("Error in /cohere/v2/chat: %s", e)
return JSONResponse(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,
content=CohereError(
message=sanitize_message(str(e)),
id=_request_id(raw_request),
).model_dump(exclude_none=True),
)
return _error_response(create_error_response(e), raw_request)
match result:
case ErrorResponse():
@@ -194,15 +191,9 @@ if _SDK_AVAILABLE:
try:
chat_request = handler.to_chat_completion_request(request)
result = await render_handler.render_chat_request(chat_request)
except Exception as e: # noqa: BLE001 - report as 500 for parity
except Exception as e:
logger.exception("Error in /cohere/v2/chat/render: %s", e)
return JSONResponse(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,
content=CohereError(
message=sanitize_message(str(e)),
id=_request_id(raw_request),
).model_dump(exclude_none=True),
)
return _error_response(create_error_response(e), raw_request)
if isinstance(result, ErrorResponse):
return _error_response(result, raw_request)