Error Hierarchy
All Chirp exceptions inherit fromChirpError. HTTP errors carry a status code and detail message.
Raising Errors
Raise HTTP errors in route handlers to trigger error responses:
from chirp import NotFound, HTTPError
@app.route("/users/{id:int}")
async def get_user(id: int):
user = await db.fetch_one("SELECT * FROM users WHERE id = ?", [id])
if not user:
raise NotFound(f"User {id} not found")
return Template("user.html", user=user)
@app.route("/premium")
def premium():
if not g.user or not g.user.is_premium:
raise HTTPError(403, "Premium access required")
return Template("premium.html")
NotFound
raise NotFound("Page not found") # 404 with detail message
raise NotFound() # 404 with default message
MethodNotAllowed
Raised automatically by the router when a path matches but the HTTP method does not. The response includes anAllowheader listing valid methods and the allowed methods in the body.
ConfigurationError
Raised at startup for invalid configuration:
# These raise ConfigurationError:
# - Using SessionMiddleware without secret_key
# - Using CSRFMiddleware without secret_key
# - Returning Template without kida integration configured
Error Handlers
Register custom error handlers by status code or exception type:
@app.error(404)
def handle_404(request: Request):
return Template("errors/404.html", path=request.path)
@app.error(500)
def handle_500(request: Request, error: Exception):
return Template("errors/500.html", error=str(error))
Error handlers support the same return-value system as route handlers. You can return a Template, Fragment, Response, string, or dict.
Handler Signatures
Error handlers support flexible signatures:
# Zero arguments
@app.error(404)
def handle_404():
return "Not Found"
# Request only
@app.error(404)
def handle_404(request: Request):
return Template("404.html", path=request.path)
# Request and error
@app.error(500)
def handle_500(request: Request, error: Exception):
log_error(error)
return Template("500.html")
Chirp inspects the handler signature and injects the appropriate arguments.
Exception Type Handlers
Handle specific exception types:
from chirp import ValidationError
@app.error(ValidationError)
def handle_validation(request: Request, error: ValidationError):
return Response(str(error)).with_status(422)
Fragment-Aware Error Handling
When an htmx request triggers an error, Chirp renders error fragments instead of full error pages:
@app.error(404)
def handle_404(request: Request):
if request.is_fragment:
return Fragment("errors/404.html", "error_message", path=request.path)
return Template("errors/404.html", path=request.path)
Built-in error handling automatically returns <div class="chirp-error">snippets for htmx requests.
Terminal Error Formatting
During development, Chirp formats errors for the terminal with structured, readable output instead of raw Python tracebacks.
Template Errors
When a Kida template error occurs, Chirp displays the error with its code, source snippet, and route context:
-- Template Error -----------------------------------------------
K-RUN-001: Undefined variable 'usernme' in base.html:42
|
> 42 | <h1>{{ usernme }}</h1>
|
Hint: Did you mean 'username'?
Docs: https://kida.dev/docs/errors/#k-run-001
Route: GET /dashboard
-----------------------------------------------------------------
Non-Template Errors
For other exceptions, Chirp filters tracebacks to show only application frames (hiding framework and stdlib internals).
Traceback Verbosity
Control terminal traceback style with theCHIRP_TRACEBACKenvironment variable:
| Value | Behavior |
|---|---|
compact |
App frames only (default) |
full |
Full Python traceback |
minimal |
Single-line error summary |
# Show full tracebacks during deep debugging
CHIRP_TRACEBACK=full chirp run
# Minimal output for CI/production
CHIRP_TRACEBACK=minimal chirp run
Streaming and SSE Errors
Errors during chunked streaming or SSE connections use the same formatting pipeline. In debug mode, streaming errors render as a visible<div class="chirp-error"> element in the page, and SSE errors are sent as an event: errormessage the client can handle.
Debug Pages
WhenAppConfig(debug=True), unhandled exceptions render a detailed debug page with:
- Full traceback with source code context
- Request details (method, path, headers, query parameters)
- Application configuration
- Template error panel with error code, source snippet, and docs link (for Kida errors)
Warning
Debug pages expose internal details. Never enabledebug=Truein production.
Next Steps
- API Reference -- Complete API surface
- Routes -- Error handlers and route registration
- Configuration -- Debug mode settings