question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[FEATURE] Allow customization of validation error

See original GitHub issue

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).

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:15
  • Comments:16 (1 by maintainers)

github_iconTop GitHub Comments

9reactions
ushucommented, Jan 7, 2021

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:

from typing import Optional
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}

it will present the default schema il http://localhost:8000/docs:

image

But if I just overwrite the validation_error_response_definition in the fastapi.openapi.utils module it changes the default schema used by OpenAPI:

from typing import Optional
from fastapi import FastAPI

# import the module we want to modify
import fastapi.openapi.utils as fu

app = FastAPI()

# and override the schema
fu.validation_error_response_definition = {
    "title": "HTTPValidationError",
    "type": "object",
    "properties": {
        "error": {"title": "Message", "type": "string"}, 
    },
}

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}

gives:

image
7reactions
Acerinthcommented, Apr 28, 2021

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):

from pydantic import BaseModel
from typing import Optional, List

class Error(BaseModel):

    loc: Optional[List[str]] = None
    msg: str
    type: str

class ErrorResponse(BaseModel):
    detail: List[Error]

Then you use Pydantic model ErrorResponse in responses when defining your app:

app = FastAPI(title="My API", description="Some description here",
                     responses={status.HTTP_400_BAD_REQUEST: {"model": ErrorResponse}})

Then you override the default exception handler (like in the tutorial):

from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return JSONResponse(content=jsonable_encoder({"detail": exc.errors()}),
                        status_code=status.HTTP_400_BAD_REQUEST)

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:

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        routes=app.routes
    )

    http_methods = ["post", "get", "put", "delete"]
    # look for the error 422 and removes it
    for method in openapi_schema["paths"]:
        for m in http_methods:
            try:
                del openapi_schema["paths"][method][m]["responses"]["422"]
            except KeyError:
                pass

    app.openapi_schema = openapi_schema
    return app.openapi_schema


app.openapi = custom_openapi

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 servers to the openapi_schema as well, to have the proper routing in Swagger/Redoc. For example:

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        routes=app.routes,
        servers=[{
            "url": "/subapi"
        }]
    )
    # the rest as above

P.S. If you really wanna be persistent, and remove even the ValidationError and HTTPValidationError from schemas, you can add the following to your custom_openapi() method:

    for schema in list(openapi_schema["components"]["schemas"]):
        if schema == "HTTPValidationError" or schema == "ValidationError":
            del openapi_schema["components"]["schemas"][schema]

Hope this helps! 😄

Thanks again @tiangolo for all the awesome work on the framework! 🚀

Read more comments on GitHub >

github_iconTop Results From Across the Web

In screen flow, allow custom validation error messages on ...
When a component is added to a screen and the 'Required' checkbox is checked, allow Admins to enter a custom error message to...
Read more >
Providing custom error messages for built-in HTML5 form ...
How to customize built-in form validation error messages · Grab the input element(s) with a querySelector / querySelectorAll . · Add an event ......
Read more >
Custom Validation Error Messages - Your own talent platform
This guide describes how an admin can create custom error messages to inform a user on the required inputs in a custom data...
Read more >
Allow forms to set custom validation error messages ... - Drupal
Allow forms to set custom validation error messages on required fields · Problem/Motivation · Proposed resolution · Remaining tasks · User interface ...
Read more >
About Validation Error Messages - Contentstack
If you do not specify any custom error message in this property (and assuming that you have specified certain rules in Validation (regex)...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found