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_handlerexception handler.Exceptions inheriting from this class should set the class variable
errorto a unique error code (normally composed of lowercase letters and underscores) for that error, and the class variablestatus_codeto 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 themsgkey 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 thelocationgiving 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
locationorfield_pathwhen 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_pathmay be a hierarchical list of elements in a complex structure. For example, for a POST handler that accepts JSON and finds a problem in theaddresskey of theuserfield, setfield_pathto["user", "address"].Some errors, such as permission denied errors, will not have any meaningful associated location information. In this case, do not specify
locationorfield_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
ErrorModelPydantic model, this class, and theclient_request_error_handlerexception 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
ErrorModelvia theto_dictmethod. Theclient_request_error_handlerexception handler uses that facility to transform this exception into afastapi.responses.JSONResponsewith an appropriate status code.The FastAPI error serialization format supports returning multiple errors at a time as a list in the
detailkey. This functionality is not supported by this exception class.