Module

server.terminal_errors

Terminal error formatting for chirp development server.

Provides structured, human-readable error output for the terminal during chirp run. Replaces raw logger.exception()with clean diagnostics that highlight the useful information.

For startup errors:

Maps known startup exceptions (port conflicts, TLS misconfiguration,
lifespan failures, config validation) to clean, actionable messages
via ``format_startup_error()``.  Returns ``None`` for unrecognised
errors so the caller can fall back to the default traceback.

For Kida template errors:

Calls ``exc.format_compact()`` and adds Chirp-specific context (route,
method, path). Produces output like::

    -- Template Error -----------------------------------------------
    K-RUN-001: Undefined variable 'usernme' in base.html:42

       |
    >42 | <h1>{{ usernme }}</h1>
       |

    Route:  GET /dashboard
    Hint:   Use {{ usernme | default('') }} for optional variables
    Docs:   https://kida.dev/docs/errors/#k-run-001
    -----------------------------------------------------------------

For non-template errors: Uses configurable traceback verbosity (compact/full/minimal) controlled by theCHIRP_TRACEBACKenvironment variable.

Functions

_is_kida_error 1 bool
Check if an exception originates from the kida template engine.
def _is_kida_error(exc: BaseException) -> bool
Parameters
Name Type Description
exc BaseException
Returns
bool
_plain_error_message 1 str
Error message safe for HTTP/SSE/JSON (no ANSI codes).
def _plain_error_message(exc: BaseException) -> str
Parameters
Name Type Description
exc BaseException
Returns
str
_is_app_frame 1 bool
True if the frame is from the application (not stdlib/site-packages).
def _is_app_frame(filename: str) -> bool
Parameters
Name Type Description
filename str
Returns
bool
format_template_error 2 str
Format a Kida template error for logging (plain text, no ANSI). Uses the same …
def format_template_error(exc: BaseException, request: Request | None = None) -> str

Format a Kida template error for logging (plain text, no ANSI).

Uses the same compact body as_plain_error_message() — Kida's format_compact()with ANSI stripped so JSON/structured logs stay readable.

Parameters
Name Type Description
exc BaseException

A Kida template exception (TemplateError subclass).

request Request | None

The request that triggered the error (optional).

Default:None
Returns
str
format_compact_traceback 1 str
Format a non-template error with compact traceback. Shows only application fra…
def format_compact_traceback(exc: BaseException) -> str

Format a non-template error with compact traceback.

Shows only application frames + error summary, suppressing framework internals from kida, starlette, uvicorn, anyio.

Parameters
Name Type Description
exc BaseException

Any exception.

Returns
str
format_minimal_error 1 str
One-line error summary for minimal verbosity.
def format_minimal_error(exc: BaseException) -> str
Parameters
Name Type Description
exc BaseException

Any exception.

Returns
str
log_error 2 None
Log an internal error with appropriate formatting. Detects Kida template error…
def log_error(exc: BaseException, request: Request | None = None) -> None

Log an internal error with appropriate formatting.

Detects Kida template errors and formats them cleanly. For non-template errors, uses the traceback verbosity level fromCHIRP_TRACEBACK (compact, full, minimal). Defaults to compact.

This replaces the rawlogger.exception()call in handle_internal_error().

Parameters
Name Type Description
exc BaseException

The exception that caused the 500 error.

request Request | None

The request that triggered the error (optional for streaming/SSE contexts where a request may not be available).

Default:None
format_startup_error 2 str | None
Map a startup exception to a clean, actionable terminal message.
def format_startup_error(exc: BaseException, *, cli: bool = False) -> str | None
Parameters
Name Type Description
exc BaseException

The exception raised during startup.

cli bool

WhenTrue, hints reference chirp run --port instead of app.run(port=...). Returns Noneif the exception is not a recognised startup error (caller should re-raise or fall back to default handling).

Default:False
Returns
str | None
_with_cause 2 str
Append ``__cause__`` context when present (e.g. LifespanError wrapping a DB err…
def _with_cause(msg: str, exc: BaseException) -> str

Append__cause__context when present (e.g. LifespanError wrapping a DB error).

Parameters
Name Type Description
msg str
exc BaseException
Returns
str