Add a handler to make the structure of validation errors consistent.

main
KKlochko 1 month ago
parent 763773ee51
commit 59caa6a0ab
Signed by: KKlochko
GPG Key ID: 572ECCD219BBA91B

@ -1,4 +1,5 @@
from fastapi import FastAPI, HTTPException, status from fastapi import FastAPI, HTTPException, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from starlette.requests import Request from starlette.requests import Request
from typing import List, Optional, Union, Dict, Any, Tuple from typing import List, Optional, Union, Dict, Any, Tuple
@ -71,6 +72,36 @@ async def http_exception_handler(request: Request, exc: HTTPException):
content=response_body content=response_body
) )
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
"""
Handles Pydantic validation errors (normally 422) and returns them as 400 Bad Request
with a consistent error structure.
Return first validation error.
"""
# Extract validation error details
errors = exc.errors()
# Get first error:
location = " -> ".join(str(l) for l in errors[0]["loc"])
error_message = f"{location}: {errors[0]['msg']}"
response_body = {
"error": {
"code": "INVALID_INPUT",
"message": error_message,
"details": {}
}
}
return JSONResponse(
# Changed from 422 to 400
status_code=400,
content=response_body
)
# ==================== Endpoints ==================== # ==================== Endpoints ====================
@app.get("/health") @app.get("/health")
async def health_check(): async def health_check():

@ -89,7 +89,7 @@ class TestGeneralEndpoint:
"entities": [] "entities": []
} }
response = api_client.post(f"{BASE_URL}/general", json=payload) response = api_client.post(f"{BASE_URL}/general", json=payload)
assert response.status_code == 422 # Pydantic validation error assert response.status_code == 400
def test_error_empty_texts_list(self, api_client): def test_error_empty_texts_list(self, api_client):
"""Test error with an empty texts list""" """Test error with an empty texts list"""
@ -109,7 +109,7 @@ class TestGeneralEndpoint:
"threshold": threshold "threshold": threshold
} }
response = api_client.post(f"{BASE_URL}/general", json=payload) response = api_client.post(f"{BASE_URL}/general", json=payload)
assert response.status_code == 422 assert response.status_code == 400
@pytest.mark.parametrize("threshold", [0.0, 0.5, 1.0]) @pytest.mark.parametrize("threshold", [0.0, 0.5, 1.0])
def test_valid_threshold_range(self, api_client, threshold): def test_valid_threshold_range(self, api_client, threshold):

@ -73,7 +73,7 @@ class TestRelationExtractionEndpoint:
"relations": [] "relations": []
} }
response = api_client.post(f"{BASE_URL}/relation-extraction", json=payload) response = api_client.post(f"{BASE_URL}/relation-extraction", json=payload)
assert response.status_code == 422 assert response.status_code == 400
def test_error_both_text_and_texts(self, api_client): def test_error_both_text_and_texts(self, api_client):
"""Test error when both text and texts are present""" """Test error when both text and texts are present"""

Loading…
Cancel
Save