Problem Details for HTTP APIs
This registry acts as a well-known location for problem detail types returned by various APIs. It acts as a central registry to promote reuse and clarity of problem detail types conforming to RFC 9457, formerly RFC 7807.
Problem Types
| Problem type | Description |
|---|---|
| Already Exists | The request attempted to create a resource that already exists. |
| Business Rule Violation | The request is deemed invalid as it failed business rule checks. |
| Invalid Body Property Format | One or more of the body properties was malformed. |
| Invalid Body Property Value | One or more of the body property values are invalid. |
| Invalid Request Header Format | One or more of the request headers was malformed. |
| Invalid Request Parameter Format | One or more of the query or path parameters was malformed. |
| Invalid Request Parameter Value | One or more of the query or path parameter values are invalid. |
| Invalid State Transition | The requested transition is not valid for the current item status. |
| Missing Body Property | The request is missing an expected body property. |
| Missing Request Header | The request lacked an expected header. |
| Missing Request Parameter | The request is missing a query or path parameter. |
| License Cancelled | The client license has been cancelled, rendering the service unavailable. |
| License Expired | The client license has expired, rendering the service unavailable. |
| Validation Error | The request is invalid and deemed unprocessable. |
Common Problem Types
The following types can also be leveraged for convenience; however, the recommendation is to utilize the IANA registry for generic/common types.
| Problem type | Description |
|---|---|
| Bad Request | The client request is invalid or malformed. |
| Conflict | The request conflicts with the current state of the target resource. |
| Failed Dependency | The requested action depends on another action that failed. |
| Forbidden | The request is not authorized for the resource. |
| Gone | The requested resource is no longer available and the condition is likely permanent. |
| Insufficient Storage | The server lacks enough storage to complete the requested action. |
| Invalid Parameters | One or more of the parameters was malformed. |
| Method Not Allowed | The target resource does not support the request method. |
| Not Acceptable | No representation matches the request's content negotiation preferences. |
| Not Found | The requested resource could not be found. |
| Not Implemented | The server does not support the functionality required by the request. |
| Request Timeout | The server timed out while waiting to receive the request. |
| Server Error | The server encountered an unexpected error. |
| Service Unavailable | The requested service is currently unavailable. |
| Unauthorized | The client request missed or malformed its credentials. |
| Unavailable For Legal Reasons | The requested resource is unavailable because of a legal restriction. |
| Unprocessable Content | The request is syntactically correct but cannot be processed. |
When necessary, a Problem Detail response MAY include additional detail on the problems that have occurred. The additional errors MUST be under the errors collection, which itself follows the JSON Schema defined in our GitHub repo.
Python Usage
Install the package in an environment with Pydantic 2:
pip install http-apis-problems-detail
Use the generated models to build responses with fixed registry fields and optional extension members:
import http_apis_problems_detail as registry
problem = registry.MissingRequestParameter(
instance="https://api.example.test/problems/abc123",
code="400-03",
errors=[
registry.ErrorDetail(
detail="The query parameter limit is required.",
parameter="limit",
)
],
)
payload = problem.model_dump(mode="json", exclude_none=True)
The resulting payload includes the registered type, status, title, and detail values:
{
"instance": "https://api.example.test/problems/abc123",
"code": "400-03",
"errors": [
{
"detail": "The query parameter limit is required.",
"parameter": "limit"
}
],
"type": "https://terradue.github.io/http-apis-problems-detail/missing-request-parameter",
"status": 400,
"title": "Missing request parameter",
"detail": "The request is missing an expected query or path parameter.",
}
ProblemDetails and ErrorDetail allow additional provider-specific fields, while generated problem classes use Pydantic literal fields to protect the registered type, status, title, and detail values.
FastAPI Integration
The FastAPI integration requires Python 3.10 or newer. FastAPI is included as a package dependency:
pip install http-apis-problems-detail
Register an exception handler that returns the problem detail as the response body, then raise a ProblemRegistryException subclass from a route:
from fastapi import FastAPI, Request, status as http_status
from http_apis_problems_detail import ErrorDetail
from http_apis_problems_detail.fastapi import (
PROBLEM_RESPONSES,
ProblemRegistryException,
NotFoundException,
problem_registry_exception_handler,
)
app = FastAPI()
app.add_exception_handler(ProblemRegistryException, problem_registry_exception_handler)
@app.get(
"/resources/{resource_id}",
responses={
http_status.HTTP_404_NOT_FOUND: PROBLEM_RESPONSES[http_status.HTTP_404_NOT_FOUND]
},
)
async def get_resource(resource_id: str, request: Request) -> dict[str, str]:
raise NotFoundException(
request=request,
errors=ErrorDetail(parameter="resource_id", detail=f"Resource '{resource_id}' was not found.")
)
The example works as follows:
- Import the integration helpers.
PROBLEM_RESPONSESmaps HTTP status codes to response model definitions that FastAPI can include in its OpenAPI document.NotFoundExceptionrepresents the registered Not Found problem, whileProblemRegistryExceptionis the common base class for the registry exceptions. - Register the exception handler.
app.add_exception_handler(...)installsproblem_registry_exception_handlerfor the base exception and its subclasses. The handler sends the serialized problem directly as the response body, using the problem's HTTP status and theapplication/problem+jsoncontent type. - Document the route's error response. The
responsesargument selects the HTTP 404 entry fromPROBLEM_RESPONSES, so FastAPI documents theNotFoundschema underapplication/problem+json. Each entry contains a schema generated from the registered models, with nested schemas included directly, so no custom OpenAPI handler is needed. This declaration describes the response in OpenAPI; raising the exception produces the response at runtime. For status codes shared by multiple problem types, the schema lists those alternatives usinganyOf. - Use the incoming request to identify the occurrence. FastAPI supplies
resource_idfrom the path and injects the currentRequest. Passingrequest=requestlets the exception set the problem'sinstanceto the request URL, with the query string removed. - Raise the registered problem.
NotFoundExceptionsupplies the registeredtype,status,title, anddetailfields. This minimal example always raises HTTP 404; in an application, raise it when the resource lookup fails and return the resource when it succeeds.
To document every registered problem response on a route, pass responses=PROBLEM_RESPONSES. Select individual status entries, as above, when only those responses apply.