error.py
An error.py is an error boundary for the folder
it lives in. When a page — or a layout below that folder — raises, Caspian renders the
nearest ancestor error.py instead of the failed subtree.
The file
Export page(error: ErrorInfo) and return markup through html(...),
exactly like a route. It may declare module-level metadata.
src/app/dashboard/error.py
# src/app/dashboard/error.py
from casp.component_decorator import html
from casp.errors import ErrorInfo
def page(error: ErrorInfo):
return html(r"""
<section class="p-8">
<p class="text-xs uppercase">{{ error.status }} · {{ error.reason }}</p>
<h1 class="text-2xl font-semibold">Something went wrong</h1>
<p>{{ error.message }}</p>
{% if error.request_id %}<small>Reference: {{ error.request_id }}</small>{% endif %}
</section>
""", error=error)
ErrorInfo is already safe
| Field | Contents |
|---|---|
| status / reason / code | The HTTP status and its reason phrase |
| message | The public message; a generic sentence for an unexpected exception or an unmarked 5xx in production |
| request_id | The X-Request-Id users can quote to support |
| details | Structured public context, e.g. details["errors"] from a ValidationError |
| trace | The traceback in development; always None in production |
Raise casp.errors.HttpError
to choose the status and what users see. The legacy signature page(error_message, error_trace=None)
is still supplied for older apps.
Scope rules
src/app/
layout.py # wraps every error page below
error.py # root fallback (also middleware / framework failures)
not_found.py # every 404
dashboard/
layout.py # still wraps dashboard/error.py
error.py # boundary for /dashboard/**
reports/
layout.py # skipped when a report page fails
index.py
-
src/app/dashboard/error.pycovers every page undersrc/app/dashboard/**;src/app/error.pyis the app-wide fallback, including failures outside any page. - Layouts at and above the boundary's folder still wrap the error page; layouts below it are skipped, because one of them may be what failed.
- A boundary that itself raises yields to the next ancestor. With none left, a minimal escaped page is served.
-
A 404 renders the global
not_found.pyinstead. -
Error responses carry the error's status,
Cache-Control: no-store, andX-Request-Id.
Error Handling
HttpError, RPC error shapes, Problem Details, and request correlation.