Exception Hierarchy
Understanding how these exception types relate to each other is the first step to handling them correctly:FastAPI HTTPExceptionis a subclass ofStarletteHTTPException.RequestValidationErroris not anHTTPException— it’s a separate class.- All of them ultimately inherit from Python’s
Exception.
The Three Exception Types
1. HTTP Exceptions
HTTP exceptions represent expected errors that you intentionally raise when a business condition fails — a resource isn’t found, a user lacks permission, or a conflict exists.StarletteHTTPException (not FastAPI HTTPException) so that it also catches errors raised internally by FastAPI and Starlette, such as 404 Route Not Found and 405 Method Not Allowed:
Using
StarletteHTTPException in your handler catches both exceptions raised by your code (raise HTTPException(404, ...)) and those raised internally by FastAPI — such as when a client requests a route that doesn’t exist.2. Request Validation Exceptions
Before FastAPI calls your route function, Pydantic validates the incoming data. If validation fails — wrong type, missing required field, value out of range — FastAPI raises aRequestValidationError. Your function is never executed.
{"age": "abc"}, FastAPI raises RequestValidationError and returns 422.
Register a custom handler to format validation errors to your liking:
3. Programming Exceptions
These are unexpected runtime errors caused by bugs in your code — division by zero, attribute access onNone, key errors, etc.:
Request Flow with Exception Handling
HTTPException will never fall through to the generic Exception handler.
Project Structure for Exception Handlers
Exception handlers are registered once for the entire application — not inside individual routers. A clean pattern is to centralise them in a single file:core/exceptions.py:
main.py: