Error Pages#
The error_page utility replaces CherryPy’s default error pages with a more flexible error handler.
It generates error responses based on the response Content-Type, returning either:
an HTML page (default),
a JSON error response for
application/jsonplain text for
text/plain.
If available, the HTML error page is rendered using Jinja2 with a template named error_page.html.
⚠️ Note: For 404 errors, the error handler sanitizes the error message to avoid leaking path information. A generic message is returned instead of exposing the requested path.
Setup#
from cherrypy_foundation.error_page import error_page
cherrypy.config.update({
'error_page.default': error_page,
})
Features#
Content Negotiation#
The error handler automatically detects the expected response format:
HTML Response (default for browsers):
GET /invalid-page HTTP/1.1
Accept: text/html
HTTP/1.1 404 Not Found
Content-Type: text/html
<!DOCTYPE html>
<html>
<head><title>404 Not Found</title></head>
<body>
<h2>404 Not Found</h2>
<p>Nothing matches the given URI</p>
</body>
</html>
JSON Response (for API clients):
GET /api/invalid HTTP/1.1
Accept: application/json
HTTP/1.1 404 Not Found
Content-Type: application/json
{"message": "Nothing matches the given URI", "status": "404 Not Found"}
Plain Text Response:
GET /invalid HTTP/1.1
Accept: text/plain
HTTP/1.1 404 Not Found
Content-Type: text/plain
Nothing matches the given URI
Server Error Logging#
All internal server error 500 are automatically logged with full traceback information:
@cherrypy.expose
def broken(self):
raise ValueError("Something went wrong!")
# Logs: error page status=500 Internal Server Error message=ValueError: Something went wrong!
# [full traceback]
Custom Error Pages with Jinja2#
To use custom error page templates, create an error_page.html template in your Jinja2 environment:
The following variables are available in the error_page.html template:
status(str): HTTP status code and message (e.g., “404 Not Found”)message(str): Detailed error messagetraceback(str): Stack trace (only for server errors when debug mode is enabled)version(str): CherryPy version
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ status }}</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<div class="alert alert-danger">
<h1>{{ status }}</h1>
<p>{{ message }}</p>
{% if traceback %}
<details>
<summary>Technical Details</summary>
<pre>{{ traceback }}</pre>
</details>
{% endif %}
</div>
</div>
</body>
</html>
Complete Example#
import cherrypy
from cherrypy_foundation.error_page import error_page
# Setup Jinja2
env = cherrypy.tools.jinja2.create_env(
package_name=__package__,
)
# Configure error handler
cherrypy.config.update({
'error_page.default': error_page,
})
@cherrypy.tools.jinja2(env=env)
class Root:
@cherrypy.expose
@cherrypy.tools.jinja2(template='index.html')
def index(self):
return {}
@cherrypy.expose
def not_found(self):
# Will trigger 404 error page
raise cherrypy.NotFound()
@cherrypy.expose
def server_error(self):
# Will trigger 500 error page with logging
raise ValueError("Database connection failed")
@cherrypy.expose
@cherrypy.tools.json_out()
def api_endpoint(self):
# API errors will return JSON
raise cherrypy.HTTPError(400, "Invalid request parameters")
if __name__ == '__main__':
cherrypy.quickstart(Root())