Description
In the case of an invalid parameter in the request (e.g. header, query, etc.) fastapi returns a 422 status code with the following example body:
{
"detail": [
{
"loc": [
"header",
"foo-bar"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Firstly, I was wondering what are the reasons for such choice instead of the most common 400 status code. It seems to me a bit strange, especially in the case where a required header is missing, as I would think this classifies as a syntactic error (from description of 422 versus 400 codes).
As such, is there any easy way to change default return http code on validation errors, while ideally keeping the same return body whose structure is pretty neat, instead of defining a custom schema as kind of described in issue #429 ?
from what I understand, following this answer https://github.com/tiangolo/fastapi/issues/553#issuecomment-533644801 retains the response structure while changing the status code, without defining an elaborate custom schema. It doesn't update the status codes in the automatically generated docs though... Unless we define a custom exception.
The difference between 422 and 400 becomes a bit subjective.
The rationale is that the error is not about using the protocols and languages incorrectly (HTTP, JSON) nor about doing something otherwise not allowed or incorrect (like performing an operation without enough privileges), but about sending invalid contents, even though using the correct content format (JSON) through the correct channel (valid HTTP).
But I acknowledge that the election between 422 vs others is interpretable and subjective.
The second reason is that Flask-apispec with Marshmallow used 422 too, I thought that was a good idea.
And the other advantage is that you can then separate a whole class of errors, validation errors, that are created automatically by your FastAPI app. And handle them all in a consistent way in your client, without having to do some extra inspections of the contents to decide if it's a validation error or not.
And then you can raise 400 errors in your own code, and know that those 400 errors will be something specific that you raise, and handle them in a different, custom way in your client.
You can override the validation errors including the status code, here are the docs: https://fastapi.tiangolo.com/tutorial/handling-errors/#override-request-validation-exceptions
@tiangolo The only issue with this approach in the docs is that auto-generated documentation doesn't reflect the updated status code. The second issue, perhaps a more pedantic one, is that I also have to define the response structure again, when all I want to do is change the status code.
There's a very straightforward way to change the status code in webargs: https://webargs.readthedocs.io/en/latest/advanced.html#returning-http-400-responses
Is there any way we could have a way to define a custom status code for validation exceptions, and have that reflected in the generated docs, without defining and raising custom exceptions?
Thanks @tiangolo and @yusra-haider for your replies. Sound good.
@yusra-haider yep. Check the docs there, in the same link as above. You can add a custom exception handler without creating a custom exception: https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body
Thanks @yiannis-kt for reporting back and closing the issue :+1:
Hey @tiangolo , sorry for reviving this. But I'm looking for a way of changing the status code in the generated docs (I changed the validation_exception_handler so that it returns 400 and the body of the request)
According to your last message I understand there is a way of achieving this, but I'm not being able to understand how by reading the section you linked. Is it indeed possible?
Hey @tiangolo, I am also trying to reflect the updated status_code into the auto-doc without success, fastapi is really nice and I'm trying to convince a client to use it and auto-doc is a key argument !
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request,
exc: RequestValidationError
):
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
)
Btw, thanks a lot for this framework and your dedication :) !
A discussion about a solution is happening here #1376
Most helpful comment
@tiangolo The only issue with this approach in the docs is that auto-generated documentation doesn't reflect the updated status code. The second issue, perhaps a more pedantic one, is that I also have to define the response structure again, when all I want to do is change the status code.
There's a very straightforward way to change the status code in webargs: https://webargs.readthedocs.io/en/latest/advanced.html#returning-http-400-responses
Is there any way we could have a way to define a custom status code for validation exceptions, and have that reflected in the generated docs, without defining and raising custom exceptions?