ClientRequestError

exception safir.fastapi.ClientRequestError(message, location=None, field_path=None)

Represents an error in a client request.

This is a base class for exceptions representing expected errors in client requests. Expected here means that the error should result in a 4xx HTTP error code with an error message in the body and do not represent a server failure that should produce alerts. It should normally be used in conjunction with the client_request_error_handler exception handler.

Exceptions inheriting from this class should set the class variable error to a unique error code (normally composed of lowercase letters and underscores) for that error, and the class variable status_code to the HTTP status code this exception should generate (if not 422, the default).

location

The part of the request giving rise to the error. This can be set by catching the exception in the part of the code that knows where the data came from, setting this attribute, and re-raising the exception.

field_path

Field, as a hierarchical list of structure elements, within that part of the request giving rise to the error. As with location, can be set by catching and re-raising.

Parameters:
  • message (str) – Error message, used as the msg key in the serialized error.

  • location (ErrorLocation | None, default: None) – The part of the request giving rise to the error. This may be omitted if the error message does not have meaningful location information, or to set this information via the corresponding attribute in a later exception handler.

  • field_path (list[str] | None, default: None) – Field, as a hierarchical list of structure elements, within the location giving rise to the error. This may be omitted if the error message does not have meaningful location information, or to set this information via the corresponding attribute in a later exception handler.

Examples

This class is meant to be subclassed. For example:

from fastapi import status
from safir.fastapi import ClientRequestError

class UnknownUserError(ClientRequestError):
    error = "unknown_user"
    status_code = status.HTTP_404_NOT_FOUND

If the location of the error is known when it is raised, it can be passed to the constructor. If a given error message always stems from the same location information, override __init__ of the corresponding child exception class to pass that location information to the parent constructor.

More commonly, the location information is only known to the handler, but the exception will be raised by internal service code. In this case, do not specify location or field_path when raising the exception, and catch and re-raise the exception in the handler after adding additional location information. For instance:

from safir.models import ErrorLocation


@router.get("/info/{username}", response_model=UserInfo)
async def get_info(username: str) -> UserInfo:
    try:
        return get_user_data(username)
    except UnknownUserError as e:
        e.location = ErrorLocation.path
        e.field_path = ["username"]
        raise

field_path may be a hierarchical list of elements in a complex structure. For example, for a POST handler that accepts JSON and finds a problem in the address key of the user field, set field_path to ["user", "address"].

Some errors, such as permission denied errors, will not have any meaningful associated location information. In this case, do not specify location or field_path.

Notes

FastAPI uses a standard error model for internally-generated errors (mostly Pydantic validation errors), but doesn’t provide a facility to generate errors in the same format. Safir provides the ErrorModel Pydantic model, this class, and the client_request_error_handler exception handler to fill in the gap.

This class records the necessary information to generate a FastAPI-compatible error structure and knows how to serialize itself in the same structure as ErrorModel via the to_dict method. The client_request_error_handler exception handler uses that facility to transform this exception into a fastapi.responses.JSONResponse with an appropriate status code.

The FastAPI error serialization format supports returning multiple errors at a time as a list in the detail key. This functionality is not supported by this exception class.