Skip to main content

Typed error responses for FastAPI: Literal error codes, discriminated unions in OpenAPI, single source of truth

Project description

fastapi-typed-errors

English · Русский

PyPI - Version PyPI - Python Version PyPI - Status PyPI - Downloads FastAPI Pydantic v2

GitHub Release GitHub Repo stars GitHub last commit CI Coverage Status Docs

Typed HTTP errors for FastAPI — exact Literal codes in OpenAPI, discriminated oneOf unions on the code field, and a single source of truth: the error class itself.

In plain FastAPI, raise HTTPException(404, "...") buries the error code in a string — clients can't switch on it, OpenAPI has no code type or body schema, and you hand-maintain responses={} on every route. This package makes an error a class: its HTTP status, machine-readable code and response model are declared once and derived automatically, so your error contract is typed, self-documenting, and verifiable in CI.

class NotFoundError(BaseError[Literal[ErrorCode.NOT_FOUND]]):
    http_status = HTTPStatus.NOT_FOUND


@router.get("/items/{item_id}")
def get_item(item_id: int) -> Annotated[Item, Raises[NotFoundError]]:
    if item_id == 0:
        raise NotFoundError("No item")
    return Item(item_id=item_id)

The response body is always {"code": "NOT_FOUND", "detail": "No item"}, and OpenAPI gets a 404 with the exact Literal["NOT_FOUND"] code and body model — no manual responses.

Install

pip install fastapi-typed-errors          # core + decorator
pip install "fastapi-typed-errors[cli]"   # + the CI-checker CLI

Requires Python 3.12+, FastAPI ≥ 0.115, Pydantic ≥ 2.9.

How to use it

1. Define errors and register the one handler.

from fastapi import FastAPI
from fastapi_typed_errors import BaseError, handle_base_error

app = FastAPI()
app.add_exception_handler(BaseError, handle_base_error)

2. Declare errors — pick your level of magic:

# a) by hand (core only) — write responses yourself
@app.get("/x", responses={404: {"model": error_models(NotFoundError)}})
def a() -> Item: ...


# b) declared — the marker fills responses for you
router = with_errors(APIRouter())


@router.get("/y")
def b() -> Annotated[Item, Raises[NotFoundError, ForbiddenError]]: ...


# c) automatic — no markers at all; errors are found statically
router = with_errors(APIRouter(), auto=True)


@router.get("/z")
def c(user: Annotated[User, Depends(current_user)]) -> Item:
    raise NotFoundError("...")  # auto -> 404, plus whatever current_user raises

3. Verify the contract in CI. check_raises compares what each route declares against what it can actually raise — in the endpoint and its whole dependency tree:

def test_error_contracts() -> None:
    assert check_raises(app).ok

Or as a command: fastapi-typed-errors check app.main:app (exit 0/1/2).

Why it's cool

  • Exact types in OpenAPI — a precise Literal code per status; several errors on one status become a discriminated oneOf union, so Swagger UI shows a variant picker by code.
  • Single source of truth — status, code and model declared once; the metaclass derives the rest.
  • Zero-boilerplate responses — via the Raises marker or fully automatic auto=True.
  • Static contract checkingcheck_raises catches a raise you forgot to declare (or a dead declaration) before it ships.
  • Non-invasivewith_errors patches the router in place and preserves object identity, so include_router, websockets and app-level decorators keep working natively.
  • Rigorous — fully typed (py.typed), 100% branch-covered, checked with ruff + ty at max strictness.

Documentation

📖 Full documentation — guide, customization (custom envelopes, ABC, bare-string codes), limitations, and an auto-generated API reference. Available in English and Russian.

License

MIT.


uv Ruff ty pytest Material for MkDocs Conventional Commits Semantic Versions

GitHub License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_typed_errors-1.0.1.tar.gz (21.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_typed_errors-1.0.1-py3-none-any.whl (27.0 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_typed_errors-1.0.1.tar.gz.

File metadata

  • Download URL: fastapi_typed_errors-1.0.1.tar.gz
  • Upload date:
  • Size: 21.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastapi_typed_errors-1.0.1.tar.gz
Algorithm Hash digest
SHA256 4f7e5a51f42f4daaa45893cdd1ae4004c348ffeb8f9bb60e56e8329dc4f3f356
MD5 d3cb7bf2a6e69d42509d22d20e6bc7ae
BLAKE2b-256 d27cc705bcef7cd6dd7d6ee7e6d6b3006adb4e4777317400b2b47ab30d130622

See more details on using hashes here.

File details

Details for the file fastapi_typed_errors-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fastapi_typed_errors-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 27.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastapi_typed_errors-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5fd6112421a99e6738357ac9aeb573954154ffe2479e0f42062606734c8df9e8
MD5 05db8727d31f9e148a68adf5d277426a
BLAKE2b-256 6bef30bd569c3980d21970dc98033df13d3ea8cf8fa564d022483ed04b85d4a2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page