FastAPI Exception Handling in Open Notebook: Mapping Custom Errors to HTTP Status Codes

Open Notebook centralizes its FastAPI exception handling in api/main.py by registering dedicated handlers that catch custom domain exceptions and return JSONResponse objects with specific HTTP status codes ranging from 400 to 502.

Open Notebook demonstrates a production-grade approach to API error management using FastAPI exception handling patterns. The application decouples business logic failures from HTTP transport details by defining a custom exception hierarchy in open_notebook/exceptions.py and mapping each exception type to a specific status code through centralized handlers. This architecture ensures that raising an exception anywhere in the codebase—from service layers to route handlers—automatically produces the correct HTTP response without manual status code management.

Centralized Handler Registration in api/main.py

All exception handling logic resides in api/main.py, where the FastAPI application registers specific handlers for each custom exception type. According to the Open Notebook source code, handlers are defined between lines 99–246, covering both Starlette's built-in HTTP exceptions and the application's custom domain errors.

Handling StarletteHTTPException

The base handler for standard FastAPI/Starlette HTTP errors appears at lines 99–104. This handler catches StarletteHTTPException and returns the exception's native status_code (such as 404, 403, or 500) while injecting CORS headers for browser safety.

Domain-Specific Exception Handlers

Below the base handler, individual functions map specific custom exceptions to their corresponding HTTP status codes. Each handler follows a consistent pattern: catching a specific exception class, logging the error, and returning a JSONResponse with the appropriate status code and CORS headers.

Exception-to-Status Code Mapping

The following table details how Open Notebook maps each custom exception defined in open_notebook/exceptions.py to its HTTP response:

Custom Exception HTTP Status Handler Location in api/main.py
StarletteHTTPException exc.status_code (dynamic) Lines 99–104
NotFoundError 404 Lines 176–183
InvalidInputError 400 Lines 185–192
AuthenticationError 401 Lines 194–201
RateLimitError 429 Lines 203–210
ConfigurationError 422 Lines 212–219
NetworkError 502 Lines 221–228
ExternalServiceError 502 Lines 230–237
OpenNotebookError (catch-all) 500 Lines 239–246

Custom Exception Hierarchy

All domain exceptions inherit from OpenNotebookError in open_notebook/exceptions.py. This inheritance enables the catch-all handler at lines 239–246 to return a 500 status for any unhandled domain errors, while specific subclasses trigger their dedicated handlers for more precise status codes.

Practical Implementation Examples

Raising these exceptions in router modules automatically triggers the appropriate handler. You do not need to manually set response codes or import JSONResponse in your endpoint logic.

Returning 404 for Missing Resources

When a repository query returns None, raise NotFoundError to trigger the 404 handler:


# src/api/routers/notebooks.py (simplified)

from fastapi import APIRouter, Depends
from open_notebook.exceptions import NotFoundError
from open_notebook.domain.notebook import NotebookRepository

router = APIRouter()

@router.get("/{notebook_id}")
async def get_notebook(notebook_id: str):
    notebook = await NotebookRepository.get(notebook_id)
    if notebook is None:
        # Raises 404 via the handler in api/main.py lines 176-183

        raise NotFoundError(f"Notebook {notebook_id} not found")
    return notebook

This returns a JSON payload {"detail": "Notebook abc123 not found"} with HTTP status 404 and proper CORS headers.

Returning 400 for Invalid Input

Validate request parameters and raise InvalidInputError to generate a 400 response:

from open_notebook.exceptions import InvalidInputError

@router.post("/search")
async def search(query: str):
    if not query.strip():
        # Triggers the 400 handler at api/main.py lines 185-192

        raise InvalidInputError("Search query cannot be empty")
    # Proceed with search logic...

CORS Header Injection for Error Responses

Every handler calls the private helper _cors_headers(request) before returning the JSONResponse. This ensures that error responses include the necessary Access-Control-Allow-Origin and related headers, preventing cross-origin browser blocking even when requests fail validation or authentication checks.

Summary

  • FastAPI exception handling in Open Notebook is centralized in api/main.py, where handlers registered at lines 99–246 map specific exception types to HTTP status codes.
  • Custom exceptions defined in open_notebook/exceptions.py inherit from OpenNotebookError, enabling both specific mappings (404, 400, etc.) and a catch-all 500 handler for unexpected domain errors.
  • Router modules raise these exceptions directly; the framework automatically converts them to JSONResponse objects with appropriate status codes and CORS headers.
  • The system covers standard HTTP errors (StarletteHTTPException) alongside domain-specific failures like RateLimitError (429) and ExternalServiceError (502).

Frequently Asked Questions

Where are FastAPI exception handlers defined in Open Notebook?

All exception handlers are defined and registered in api/main.py between lines 99 and 246. This file contains specific handlers for StarletteHTTPException, custom domain exceptions like NotFoundError and InvalidInputError, and a catch-all handler for the base OpenNotebookError class.

What HTTP status code does Open Notebook return when a resource is not found?

Open Notebook returns HTTP 404 when a NotFoundError is raised. The handler at lines 176–183 in api/main.py catches this specific exception and returns a JSON response with the 404 status code.

How does Open Notebook ensure CORS headers are present on error responses?

Every exception handler in api/main.py calls the private helper function _cors_headers(request) and includes these headers in the returned JSONResponse. This ensures that browser clients receive proper Access-Control-Allow-Origin headers even when the API returns 4xx or 5xx error statuses.

Can I add new custom exceptions with specific HTTP status codes to Open Notebook?

Yes. Define a new exception class in open_notebook/exceptions.py that inherits from OpenNotebookError, then register a corresponding handler in api/main.py using the @app.exception_handler() decorator. Return a JSONResponse with your desired status code and include CORS headers via _cors_headers(request) to maintain consistency with the existing error handling patterns.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →