FastAPI Custom Responses
Project description
FastAPI Custom Responses
Provides normalized response objects and error handling for FastAPI applications. All errors — validation, HTTP, and unhandled exceptions — are returned in a consistent { "success": false, "error": "..." } format with human-readable messages.
Installation
pip install fastapi-custom-responses
Quick Start
from http import HTTPStatus
from fastapi_custom_responses import EXCEPTION_HANDLERS, ErrorResponse, ErrorResponseModel, Response, SuccessResponse
from fastapi import APIRouter, FastAPI, Request
router = APIRouter()
app = FastAPI(
title="API",
description="My API",
version="1.0.0",
exception_handlers=EXCEPTION_HANDLERS,
)
class Data(Response):
example: str
@router.get(
"/",
response_model=Response[Data],
responses={
400: {"model": ErrorResponseModel, "description": "Bad request"},
500: {"model": ErrorResponseModel, "description": "Internal server error"},
},
)
async def index(_: Request) -> Response[Data]:
"""Index route."""
return Response(
success=True,
data=Data(example="hello"),
)
@router.get("/return-error")
async def error_route(_: Request) -> Response:
"""Error route."""
raise ErrorResponse(error="Your request is invalid.", status_code=HTTPStatus.BAD_REQUEST)
Note: When using OpenAPI generators, use SuccessResponse instead of Response if your endpoint has no data to return.
Error Normalization
Passing EXCEPTION_HANDLERS to your FastAPI app registers handlers that normalize all errors into a consistent JSON shape:
{
"success": false,
"error": "Human-readable error message"
}
Handled Exception Types
| Exception | Status Code | Behavior |
|---|---|---|
ErrorResponse |
Custom (default 400) |
Uses the provided error message directly |
RequestValidationError |
400 |
Pydantic validation errors are converted to human-readable messages (see below) |
HTTPException |
From exception | Uses the exception detail as the error message |
ValueError |
400 |
Uses str(exc) as the error message |
Exception (catch-all) |
500 |
Returns a generic "An unexpected error occurred" message |
Raising Errors
Raise ErrorResponse with a message and status code:
from http import HTTPStatus
from fastapi_custom_responses import ErrorResponse
raise ErrorResponse(error="Resource not found", status_code=HTTPStatus.NOT_FOUND)
You can also create one from a status code alone, which maps to a default message:
raise ErrorResponse.from_status_code(HTTPStatus.FORBIDDEN)
# → { "success": false, "error": "You don't have permission to perform this action" }
Default messages for common status codes:
| Status Code | Default Message |
|---|---|
401 |
"Authentication required" |
403 |
"You don't have permission to perform this action" |
404 |
"Resource not found" |
400 |
"Invalid request" |
500 |
"An unexpected error occurred" |
Validation Error Normalization
When a request fails Pydantic validation, FastAPI normally returns a verbose JSON array of raw Pydantic errors. With EXCEPTION_HANDLERS, these are automatically converted into concise, human-readable messages.
Before (default FastAPI):
{
"detail": [
{
"type": "missing",
"loc": ["body", "email"],
"msg": "Field required",
"input": {}
}
]
}
After (with EXCEPTION_HANDLERS):
{
"success": false,
"error": "Field 'email' is required"
}
When multiple fields fail validation, messages are joined with periods:
{
"success": false,
"error": "Field 'email' is required. Field 'age' must be a valid integer"
}
Supported Pydantic error types and their human-readable formats:
| Error Type | Example Message |
|---|---|
missing |
Field 'name' is required |
string_type |
Field 'name' must be a string |
int_type / int_parsing |
Field 'age' must be a valid integer |
float_type / float_parsing |
Field 'price' must be a valid number |
bool_type / bool_parsing |
Field 'active' must be a boolean |
enum |
Field 'status' must be one of: active, inactive |
uuid_type / uuid_parsing |
Field 'id' must be a valid UUID |
string_too_short |
Field 'name' must be at least 3 characters |
string_too_long |
Field 'name' must be at most 50 characters |
too_short / too_long |
Field 'items' must have at least 1 item |
greater_than / less_than |
Field 'age' must be greater than 0 |
greater_than_equal / less_than_equal |
Field 'age' must be at least 18 |
value_error |
Invalid email format (uses the validator message directly) |
json_invalid |
Invalid JSON in request body |
Any unrecognized error types fall back to the Pydantic error message prefixed with the field name.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_custom_responses-0.1.2.tar.gz.
File metadata
- Download URL: fastapi_custom_responses-0.1.2.tar.gz
- Upload date:
- Size: 5.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e758e354fcd42d961bdbff1c7f891e8e0cd8e24eb93b8da50032e8942283ecb
|
|
| MD5 |
947ed5cb1f6c94c8b74731ed146208c2
|
|
| BLAKE2b-256 |
c7d90e4bc04518462081e84203f5a2f9ad39baf21e5f177159b9510e2b45b4ea
|
Provenance
The following attestation bundles were made for fastapi_custom_responses-0.1.2.tar.gz:
Publisher:
publish-to-pypi.yml on julien777z/fastapi-custom-responses
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_custom_responses-0.1.2.tar.gz -
Subject digest:
1e758e354fcd42d961bdbff1c7f891e8e0cd8e24eb93b8da50032e8942283ecb - Sigstore transparency entry: 1282639758
- Sigstore integration time:
-
Permalink:
julien777z/fastapi-custom-responses@1f5d88670f76b3a5f7598b369a6bde90c48817de -
Branch / Tag:
refs/heads/claude/upgrade-pydantic-super-model-ZiGew - Owner: https://github.com/julien777z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@1f5d88670f76b3a5f7598b369a6bde90c48817de -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastapi_custom_responses-0.1.2-py3-none-any.whl.
File metadata
- Download URL: fastapi_custom_responses-0.1.2-py3-none-any.whl
- Upload date:
- Size: 7.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7787149533d7868fc5f7b3a3190ea58abce0cdee534d444af44b25075c7ae6b2
|
|
| MD5 |
bd3139fc3be28ce9c6815dbd3acadf59
|
|
| BLAKE2b-256 |
d2fbede171531175c78d1b1c9f62b4fe4dd5a9f820bf42612c33ac1230b25003
|
Provenance
The following attestation bundles were made for fastapi_custom_responses-0.1.2-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on julien777z/fastapi-custom-responses
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_custom_responses-0.1.2-py3-none-any.whl -
Subject digest:
7787149533d7868fc5f7b3a3190ea58abce0cdee534d444af44b25075c7ae6b2 - Sigstore transparency entry: 1282639783
- Sigstore integration time:
-
Permalink:
julien777z/fastapi-custom-responses@1f5d88670f76b3a5f7598b369a6bde90c48817de -
Branch / Tag:
refs/heads/claude/upgrade-pydantic-super-model-ZiGew - Owner: https://github.com/julien777z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@1f5d88670f76b3a5f7598b369a6bde90c48817de -
Trigger Event:
workflow_dispatch
-
Statement type: