Module

exceptions

Exceptions for Kida template system.

Standalone module with zero internal imports at module level, breaking the deepest circular import chain (environment → exceptions → environment).

Exception Hierarchy:

TemplateError (base) ├── TemplateNotFoundError # Template not found by loader ├── TemplateSyntaxError # Parse-time syntax error ├── TemplateRuntimeError # Render-time error with context │ ├── RequiredValueError # Required value was None/missing │ └── NoneComparisonError # Attempted None comparison (sorting) └── UndefinedError # Undefined variable access

Error Messages:

All exceptions provide rich error messages with:

  • Source location (template name, line number)
  • Expression context where error occurred
  • Actual values and their types
  • Source snippets showing the offending template line
  • Actionable suggestions for fixing

Example:

```
UndefinedError: Undefined variable 'titl' in article.html:5
   |
 5 | <h1>{{ titl }}</h1>
   |
Hint: Did you mean 'title'? Or use {{ titl | default('') }}
```

Classes

ErrorCode 2 ▼
Searchable error codes for Kida diagnostics. Format: K-{CATEGORY}-{NUMBER}. Categories cover lexer…

Searchable error codes for Kida diagnostics.

Format: K-{CATEGORY}-{NUMBER}. Categories cover lexer/parser/runtime failures plus component, warning, safety, and static-analysis findings.

Each code maps to a documentation URL for quick lookup: https://lbliii.github.io/kida/docs/errors/#k-run-001

Methods

docs_url 0 str ▼
Documentation URL for this error code.
property
def docs_url(self) -> str
Returns
str
category 0 str ▼
Error category (e.g., 'runtime', 'lexer', 'parser', 'template', 'security').
property
def category(self) -> str
Returns
str
TemplateWarning 6 ▼
Compile-time template warning (not an exception).

Compile-time template warning (not an exception).

Attributes

Name Type Description
code ErrorCode —
message str —
template_name str | None —
lineno int | None —
suggestion str | None —

Methods

format_message 0 str ▼
Format warning for display.
def format_message(self) -> str
Returns
str
KidaWarning 0 ▼
Base warning category for Kida template warnings.

Base warning category for Kida template warnings.

PrecedenceWarning 0 ▼
Operator precedence may cause unexpected results.

Operator precedence may cause unexpected results.

CoercionWarning 0 ▼
Implicit type coercion in filter.

Implicit type coercion in filter.

MigrationWarning 0 ▼
Jinja2 migration: behavior differs from Jinja2.

Jinja2 migration: behavior differs from Jinja2.

ComponentWarning 0 ▼
Component contract validation warning.

Component contract validation warning.

SourceSnippet 4 ▼
Template source context around an error line. Provides surrounding lines of template source for di…

Template source context around an error line.

Provides surrounding lines of template source for display in error messages. Used by TemplateRuntimeError and UndefinedError to show the template line where the error occurred.

Attributes

Name Type Description
lines tuple[tuple[int, str], ...]

Tuple of (line_number, line_content) pairs around the error.

error_line int

The 1-based line number where the error occurred.

column int | None

Optional column offset for caret pointer.

Methods

format 0 str ▼
Format snippet in Rust-inspired diagnostic style with colors. Returns a multi-…
def format(self) -> str

Format snippet in Rust-inspired diagnostic style with colors.

Returns a multi-line string with line numbers and the error line highlighted. Uses terminal colors when supported.

Returns
str
DiagnosticLocation 5 ▼
Surface-neutral template location for exception renderers.

Surface-neutral template location for exception renderers.

Attributes

Name Type Description
template str —
line int | None —
column int | None —
filename str | None —

Methods

format 0 str ▼
Return ``template[:line[:column]]`` without terminal styling.
def format(self) -> str
Returns
str
DiagnosticFrame 4 ▼
Surface-neutral stack frame for template/component diagnostics.

Surface-neutral stack frame for template/component diagnostics.

Attributes

Name Type Description
template str —
line int —
name str | None —

Methods

format 0 str ▼
Return a plain frame label.
def format(self) -> str
Returns
str
TemplateDiagnostic 16 ▼
Structured diagnostic data for downstream renderers. This payload intentionally stores plain strin…

Structured diagnostic data for downstream renderers.

This payload intentionally stores plain strings and immutable tuples only. HTML, markdown, and terminal escaping/styling belongs to the renderer that consumes it.

Attributes

Name Type Description
code str | None —
title str —
message str —
kind str —
location DiagnosticLocation —
source_snippet SourceSnippet | None —
hints tuple[str, ...] —
docs_url str | None —
suggestion str | None —
template_stack tuple[DiagnosticFrame, ...] —
component_stack tuple[DiagnosticFrame, ...] —
metadata tuple[tuple[str, str], ...] —

Methods

metadata_dict 0 dict[str, str] ▼
Return metadata as a regular dict for consumers that prefer mapping APIs.
def metadata_dict(self) -> dict[str, str]
Returns
dict[str, str]
format_html_fragment 0 str ▼
Render a dependency-free escaped HTML diagnostic fragment. This is intentional…
def format_html_fragment(self) -> str

Render a dependency-free escaped HTML diagnostic fragment.

This is intentionally compact and unstyled so framework debug pages can wrap it in their own chrome without inheriting terminal formatting.

Returns
str
format_html_page 1 str ▼
Render a standalone escaped HTML diagnostic page.
def format_html_page(self, *, page_title: str = 'Kida Template Error') -> str
Parameters
Name Type Description
page_title — Default:'Kida Template Error'
Returns
str
format_markdown 0 str ▼
Render a GitHub-flavored Markdown diagnostic from plain fields.
def format_markdown(self) -> str
Returns
str
TemplateError 2 ▼
Base exception for all Kida template errors. All template-related exceptions inherit from this cla…

Base exception for all Kida template errors.

All template-related exceptions inherit from this class, enabling broad exception handling:

>>> try:
...     template.render()
... except TemplateError as e:
...     log.error(f"Template error: {e}")

Attributes

Name Type Description
code ErrorCode | None

Optional ErrorCode for searchable, documentable error identification.

Methods

format_compact 0 str ▼
Format error as a structured, human-readable summary. Produces a clean diagnos…
def format_compact(self) -> str

Format error as a structured, human-readable summary.

Produces a clean diagnostic string suitable for terminal display, without Python traceback noise. Consumers (Chirp, Bengal) can call this instead of parsingstr(exc).

Format::

K-RUN-001: Undefined variable 'usernme' in base.html:42
   |
>42 | <h1>{{ usernme }}</h1>
   |
Hint: Use {{ usernme | default('') }} for optional variables
Docs: https://lbliii.github.io/kida/docs/errors/#k-run-001
Returns
str Multi-line string with error code, message, source snippet, and documentation URL.
TemplateNotFoundError 1 ▼
Template not found by any configured loader. Raised when `Environment.get_template(name)` cannot l…

Template not found by any configured loader.

Raised whenEnvironment.get_template(name)cannot locate the template in any of the loader's search paths.

Attributes

Name Type Description
code ErrorCode | None —
TemplateSyntaxError 3 ▼
Parse-time syntax error in template source. Raised by the Parser when template syntax is invalid. …

Parse-time syntax error in template source.

Raised by the Parser when template syntax is invalid. Includes source location for error reporting.

Whensource and linenoare provided, the error message includes a source snippet with the offending line. Ifcol_offsetis also given, a caret (^) points at the exact column.

Attributes

Name Type Description
code ErrorCode | None —

Methods

format_compact 0 str ▼
Format syntax error as structured terminal diagnostic.
def format_compact(self) -> str
Returns
str
Internal Methods 1 ▼
__init__ 6 ▼
def __init__(self, message: str, lineno: int | None = None, name: str | None = None, filename: str | None = None, source: str | None = None, col_offset: int | None = None)
Parameters
Name Type Description
message —
lineno — Default:None
name — Default:None
filename — Default:None
source — Default:None
col_offset — Default:None
TemplateRuntimeError 9 ▼
Render-time error with rich debugging context. Raised during template rendering when an operation …

Render-time error with rich debugging context.

Raised during template rendering when an operation fails. Provides detailed information to help diagnose the issue:

  • Template name and line number
  • The expression that caused the error
  • Actual values and their types
  • Actionable suggestion for fixing

Output Format:

        Runtime Error: 'NoneType' object has no attribute 'title'
          Location: article.html:15
          Expression: {{ post.title }}
          Values:
            post = None (NoneType)
          Suggestion: Check if 'post' is defined, or use {{ post.title | default('') }}
        ```

Attributes

Name Type Description
code ErrorCode | None —
message —

Error description

expression —

Template expression that failed

values —

Dict of variable names → values for context

template_name —

Name of the template

lineno —

Line number in template source

suggestion —

Actionable fix suggestion

Methods

format_compact 0 str ▼
Format runtime error as structured terminal diagnostic.
def format_compact(self) -> str
Returns
str
Internal Methods 1 ▼
__init__ 10 ▼
def __init__(self, message: str, *, expression: str | None = None, values: dict[str, Any] | None = None, template_name: str | None = None, lineno: int | None = None, suggestion: str | None = None, source_snippet: SourceSnippet | None = None, template_stack: list[tuple[str, int]] | None = None, component_stack: list[tuple[str, int, str]] | None = None, code: ErrorCode | None = None)
Parameters
Name Type Description
message —
expression — Default:None
values — Default:None
template_name — Default:None
lineno — Default:None
suggestion — Default:None
source_snippet — Default:None
template_stack — Default:None
component_stack — Default:None
code — Default:None
RequiredValueError 2 ▼
A required value was None or missing. Raised by the `| require` filter when a value that must be p…

A required value was None or missing.

Raised by the| requirefilter when a value that must be present is None or missing. Useful for validating required context variables.

Attributes

Name Type Description
code ErrorCode | None —

Methods

Internal Methods 1 ▼
__init__ 3 ▼
def __init__(self, field_name: str, message: str | None = None, **kwargs: Any)
Parameters
Name Type Description
field_name —
message — Default:None
**kwargs —
NoneComparisonError 2 ▼
Attempted to compare None values, typically during sorting. Raised when `| sort` or similar operat…

Attempted to compare None values, typically during sorting.

Raised when| sortor similar operations encounter None values that cannot be compared. Provides information about which items have None values for the sort attribute.

Attributes

Name Type Description
code ErrorCode | None —

Methods

Internal Methods 1 ▼
__init__ 4 ▼
def __init__(self, left_value: Any, right_value: Any, attribute: str | None = None, **kwargs: Any)
Parameters
Name Type Description
left_value —
right_value —
attribute — Default:None
**kwargs —
UndefinedError 8 ▼
Raised when accessing an undefined variable. Strict mode is enabled by default in Kida. When a tem…

Raised when accessing an undefined variable.

Strict mode is enabled by default in Kida. When a template references a variable that doesn't exist in the context, this error is raised instead of silently returning None.

Ifavailable_namesis provided, a "Did you mean?" suggestion is included when a close match is found (usingdifflib.get_close_matches).

To fix:

  • Pass the variable in render(): template.render(undefined_var="value")
  • Use the default filter: {{ undefined_var | default("fallback") }}

Attributes

Name Type Description
code ErrorCode | None —

Methods

diagnostic_hints 0 tuple[str, ...] ▼
Return ordered plain-text hints for structured renderers.
def diagnostic_hints(self) -> tuple[str, ...]
Returns
tuple[str, ...]
to_diagnostic 0 TemplateDiagnostic ▼
Return a surface-neutral diagnostic payload for this error.
def to_diagnostic(self) -> TemplateDiagnostic
Returns
TemplateDiagnostic
format_compact 0 str ▼
Format undefined variable error as structured terminal diagnostic.
def format_compact(self) -> str
Returns
str
Internal Methods 4 ▼
__init__ 9 ▼
def __init__(self, name: str, template: str | None = None, lineno: int | None = None, available_names: frozenset[str] | None = None, source_snippet: SourceSnippet | None = None, template_stack: list[tuple[str, int]] | None = None, component_stack: list[tuple[str, int, str]] | None = None, kind: str = 'variable', declared_definitions: frozenset[str] | None = None)
Parameters
Name Type Description
name —
template — Default:None
lineno — Default:None
available_names — Default:None
source_snippet — Default:None
template_stack — Default:None
component_stack — Default:None
kind — Default:'variable'
declared_definitions — Default:None
_closest_available_name 0 str | None ▼
Return the best fuzzy match from available names, if any.
def _closest_available_name(self) -> str | None
Returns
str | None
_hint_text 0 str ▼
Return the hint line shown after the error message. When the missing name matc…
def _hint_text(self) -> str

Return the hint line shown after the error message.

When the missing name matches a known top-level definition, point the user at the declaration site instead of suggestingdefault, because no default value will work — the name is meant to resolve to a {% region %} or {% def %} that is not yet bound at this point in the render (typically because it is declared but unreachable at module-init time, or render_block was called for the wrong block).

Returns
str
_nullsafe_hint_text 0 str | None ▼
Return an additional null-safe hint for attribute/key errors. For missing attr…
def _nullsafe_hint_text(self) -> str | None

Return an additional null-safe hint for attribute/key errors.

For missing attributes or dict keys under strict mode, the fix is usually to switch the access to a null-safe form rather than to supply a default at the variable level. Since v0.8.0,?.and ?[...] on Mapping receivers return Nonefor missing keys — sox?.yalone is the fix for dict-key misses; object-attr misses still need?? "" or the getfilter.

Returns
str | None

Functions

_terminal 0 ▼
Lazy import of terminal color utilities (avoids circular imports).
def _terminal()
format_template_stack 1 str ▼
Format template call stack for error messages with colors.
def format_template_stack(stack: list[tuple[str, int]] | None) -> str
Parameters
Name Type Description
stack list[tuple[str, int]] | None

List of (template_name, line_number) tuples showing include chain

Returns
str
format_component_stack 1 str ▼
Format component call stack for error messages with colors.
def format_component_stack(stack: list[tuple[str, int, str]] | None) -> str
Parameters
Name Type Description
stack list[tuple[str, int, str]] | None

List of (template_name, line_number, def_name) tuples showing the def call chain.

Returns
str
build_source_snippet 4 SourceSnippet ▼
Build a SourceSnippet from template source.
def build_source_snippet(source: str, error_line: int, *, context_lines: int = 2, column: int | None = None) -> SourceSnippet
Parameters
Name Type Description
source str

Full template source text.

error_line int

1-based line number of the error.

context_lines int

Number of lines to show before/after the error line.

Default:2
column int | None

Optional column offset for caret pointer.

Default:None
Returns
SourceSnippet