fastapi: Allow customization of validation error
Is your feature request related to a problem
I’d like to globally customize validation errors by changing (overriding) the HTTPValidationError/ValidationError and the 422 status code.
The solution you would like
Something great would be adding some parameters to the FastAPI class:
from fastapi import FastAPI
from .models import ValidationError
app = FastAPI(
validation_error_status_code=422,
validation_error_model=ValidationError
)
Describe alternatives you’ve considered
What’s currently possible (to my knowledge) is adding an item with status code 422, 4XX or default in the responses dict, but this as to be done manually for every route that will perform validation. This also prevent changing the status code to a specific value (you can either stick with 422, or have something vague like default or 4XX).
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 15
- Comments: 16
If all you errors follow the same schema, and provided you implemented the custom handler described in https://fastapi.tiangolo.com/tutorial/handling-errors/#override-request-validation-exceptions, you can just override the default schema in
openapi/utils.For example if I take the example server from the docs:
it will present the default schema il http://localhost:8000/docs:
But if I just overwrite the
validation_error_response_definitionin thefastapi.openapi.utilsmodule it changes the default schema used by OpenAPI:gives:
As this is still the topic… For all of you, who, like me, just want to change the status code to 400, but keep the default response schema AND still have it in the OpenAPI Docs, without the default 422… 😄 Here it goes…
Firstly, you describe your Pydantic models, like the original (used only for docs):
Then you use Pydantic model
ErrorResponsein responses when defining your app:Then you override the default exception handler (like in the tutorial):
With this, you will have 400 normally documented for all your routes.
If you want to remove all 422 codes from the documentation, you need to exchange the default OpenAPI schema, similar to how @tupui wrote above, or according to the tutorial here. Therefore, after defining all your path routes, add the following:
However, this works for the default API with no additional root paths. In order to make it work for such scenario, or when you want this to work only on the mounted API, you have to add
serversto theopenapi_schemaas well, to have the proper routing in Swagger/Redoc. For example:P.S. If you really wanna be persistent, and remove even the
ValidationErrorandHTTPValidationErrorfrom schemas, you can add the following to yourcustom_openapi()method:Hope this helps! 😄
Thanks again @tiangolo for all the awesome work on the framework! 🚀
The solution that would require less work and have bigger chances on being approved (based only on what I’ve seen here) is creating a flag to not add the 422 response in the swagger documentation.
The custom exception handler already handles the first problem described.
Well it works regarding what’s produced by the API, but it doesn’t regarding documentation.
Following up on @ushu excellent simple solution, I would like to add that you could directly fetch the schema from your error model, ensuring consistent behavior between your response and its documentation.
Gives:
I did similar for a single router but slightly simpler
In my application ovverhide the 422 error for 400, and overhide the responses errors for all api for the example:
message: { field_error: message_error}And the method bellow is the rewrite
exception_handlers={RequestValidationError: validation_bad_request_exception_handler}Its work fine for me =D It is just missing to change the documentation
I am doing something simpler. Just removing any ref to the error 422 in the generated OpenAPI dict:
I have hit a similar issue previously and solved it by modifying the OpenAPI spec ‘manually’ like it’s been suggested in some previous issues.
However, I think it would be useful if you could add ‘additional status codes’ and/or ‘additional responses’ to a
APIRouter()instance, which would add them to all of the routes automatically.