NAME
Punk::DevError - the development error page
SYNOPSIS
# nothing to call: in development a die becomes a debug page
punk dev # sets it for you
PUNK_ENV=development plackup app.psgi # or opt in by hand
# the default is production: the plain JSON 500
plackup app.psgi
DESCRIPTION
When the application compiles in the development environment - an opt-in: punk dev sets it, or PUNK_ENV=development, or the loaded config's env; the default is production - a die inside a handler renders a debug response instead of the bare 500: the exception message, the stack at the point of the throw with a source snippet per frame, the matched route, the request parameters and the request headers.
Content negotiation is per request: a client whose Accept includes text/html (and that did not send a JSON body) gets the HTML page; everything else gets the production JSON shape plus a trace array -
{ "errors": [ { "message": "...", "trace": ["file:12 in MyApp::x"] } ] }
so API clients in development stay parseable by the same code that parses production errors.
In any other environment this module is never loaded and the response is the C dispatcher's fixed 500 {"errors":[{"message":...}]}, byte-identical to previous releases.
HOW IT HOOKS IN
Punk::App::compile_extras installs two things at to_app, both on the cold path - the hot dispatch is untouched:
A middleware records the stack at throw time via a request-scoped $SIG{__DIE__} - the dispatcher catches dies deep in C under G_EVAL, so the frames must be captured where the die happens. The recorded message is compared against the error that reaches the handler, so an inner eval's unrelated die cannot decorate someone else's page. A die that surfaces outside the request scope (a deferred Punk::Future callback on a later loop tick) renders gracefully with the message alone.
An on_error wrapper renders the page - but only when the application's own on_error handler (if any) declined: a user handler returning a reference keeps absolute priority, in development exactly as in production.
WHAT IS REDACTED
The Cookie and Authorization header values; any header or parameter whose name matches /pass|secret|token/i; parameter values are truncated at 2KB. The session contents, the session secret and the application config are never rendered.
SYNTAX HIGHLIGHTING
If Eshu is installed the source snippets are highlighted; without it they render plain. Eshu is a recommends, never required.
SEE ALSO
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)