Error Codes

Reference for all Kida error codes with descriptions and fixes

9 min read 1876 words

Every Kida exception carries anErrorCode that categorizes the error and links to this page. Use exc.code.value to get the code string (e.g. "K-RUN-001"). For full error handling guidance, see Error Handling.

Lexer Errors (K-LEX-xxx)

Lexer errors occur during tokenization of template source.

k-lex-001

Unclosed tag — A{% or {{ or {#was not closed.

Fix: Ensure every{% has a matching %}, every {{ ` has ` }}, and every {# has #}.

k-lex-002

Unclosed comment — A comment block{# ... #}was not closed.

Fix: Add the closing#}to the comment.

k-lex-003

Unclosed variable — An output block{{ ... }}was not closed.

Fix: Add the closing}}to the expression.

k-lex-004

Token limit exceeded — The template exceeded the maximum token count.

Fix: Split the template into smaller includes or simplify the template.

Parser Errors (K-PAR-xxx)

Parser errors occur when building the template AST from tokens.

k-par-001

Unexpected token — The parser encountered a token it did not expect at this position.

Fix: Check syntax around the reported line. Common causes: misplaced{% end %}, invalid tag name, or malformed expression.

Coming from Jinja2?

When you type a Jinja2-ism that Kida does not accept, the parser error suggestion points at the Kida equivalent. Common traps:

Jinja2 Kida Hint surfaced by parser
{% macro name(...) %} {% def name(...) %} "Kida uses{% def %}for macros"
{% endmacro %} {% end %} "Kida uses unified{% end %}for all blocks"
{% namespace ns %} / namespace(count=0) {% let %} + {% export %} "Kida has nonamespace() — use {% let %} / {% export %}"
{% fill name %} {% slot name %} inside {% call %} "Kida has no{% fill %}tag"
{% set x %}...{% endset %} {% capture x %}...{% end %} "Kida uses unified{% end %}for block-capture"

See [Migrating from Jinja2](

docs/tutorials/migrate-from-jinja2

) for the complete translation table.

k-par-002

Unclosed block — A block tag (e.g.{% if %}, {% for %}) was not closed with {% end %}.

Fix: Add{% end %}for every opening block tag.

k-par-003

Invalid expression — An expression could not be parsed.

Fix: Check the expression syntax. Ensure proper operator usage, balanced parentheses, and valid filter/test syntax.

k-par-004

Invalid filter — A filter name or filter arguments are invalid.

Fix: Use a valid built-in or registered filter name. Check filter argument types.

k-par-005

Invalid test — A test name or test arguments are invalid.

Fix: Use a valid built-in or registered test name. Check test argument types.

k-par-006

Invalid identifier — A block name, fragment name, or other identifier contains a hyphen.

Fix: Use underscores instead of hyphens. For example,{% block settings-status %} should be {% block settings_status %}.

k-par-007

Unsupported syntax — A syntax construct was recognized but is not supported.

Fix: Check the error message for the specific construct. Common case:{% set x %}...{% endset %} block capture is not supported — use {% let x = ... %} or {% capture x %}...{% end %}instead.

Runtime Errors (K-RUN-xxx)

Runtime errors occur during template rendering.

k-run-001

Undefined variable — A variable or attribute was accessed that does not exist.

Fix: Pass the variable in the render context, use| default(fallback), or check with {% if var is defined %}.

k-run-002

Filter execution error — A filter raised an exception during execution.

Fix: Check the filter's input type and arguments. Use| default()for optional values.

k-run-003

Test execution error — A test raised an exception during execution.

Fix: Check the test's input type and arguments.

k-run-004

Required value was None — A required value (e.g. from| require) was None or missing.

Fix: Ensure the value is present in context or pass a valid default.

k-run-005

None comparison (sorting)sort or sortattrencountered None in a comparison.

Fix: Enablestrict_none=Trueto raise, or filter out None values before sorting.

k-run-006

Include depth exceeded — Too many nested{% include %}calls.

Fix: Reduce include nesting. Check for circular includes.

k-run-007

Generic runtime error — A Python exception occurred during rendering.

Fix: Check the traceback for the underlying cause. Ensure context values have expected types.

k-run-008

Macro not found — A{% call %} or {{ macro_name() }}referenced a macro/def that does not exist.

Fix: Ensure the macro is defined with{% def %}or imported before use. Check for typos in the name.

k-run-009

Key error — A dictionary key lookup failed during rendering.

Fix: Usedict.get(key, default) or the | default()filter to handle missing keys.

k-run-010

Attribute error — An attribute access failed during rendering.

Fix: Ensure the object has the expected attribute. Use optional chaining (?.) or | default()for optional attributes.

k-run-011

Division by zero — A division or modulo operation encountered a zero divisor.

Fix: Guard with{% if divisor != 0 %}or use a default value.

k-run-012

Type error — An operation received a value of the wrong type.

Fix: Check that the value has the expected type. Use filters like| int, | string to convert, or | default()for missing values.

k-run-013

Macro iteration — A macro was used in a{% for %} loop (e.g. {% for x in route_tabs %}). This usually means a macro and a context variable share the same name; when the variable is missing, the name resolves to the imported macro.

Fix: Rename the macro to avoid collision. Use verb-prefixed names for macros (e.g.render_route_tabs) and noun-like names for context variables (route_tabs). See Macro vs Context Variable Naming.

k-run-014

Environment garbage collected — TheEnvironmentobject was garbage collected while templates still reference it.

Fix: Keep a reference to theEnvironmentfor the lifetime of your application. Store it in a module-level variable or application state.

k-run-015

Template not compiled — A template method was called before the template was compiled.

Fix: Useenv.get_template() or env.from_string() to create templates. Do not construct Templateobjects directly.

k-run-016

No loader configuredget_template() was called on an Environmentwith no loader.

Fix: Pass a loader when creating the environment:Environment(loader=FileSystemLoader("templates/")).

k-run-017

Not in render context — A function that requires an active render context was called outside of template rendering.

Fix: Only callget_render_context() or context-dependent functions during template.render().

Template Loading Errors (K-TPL-xxx)

Template loading errors occur when resolving or loading template files.

k-tpl-001

Template not found — The loader could not find the requested template.

Fix: Check the template name and path. Verify the loader configuration (e.g.FileSystemLoaderpaths).

k-tpl-002

Syntax error in template — The template file contains invalid syntax.

Fix: Fix the syntax error at the reported line. See parser and lexer errors above for related codes.

k-tpl-003

Circular import — Two or more templates extend or include each other in a cycle.

Fix: Restructure template inheritance to eliminate the cycle. Use a shared base template or{% include %} instead of circular {% extends %}.

k-tpl-004

Definition not top-level — A{% def %} or {% region %}was declared inside another block, loop, conditional, component, or region.

Fix: Move{% def %} and {% region %}declarations to the template top level. Top-level declarations are visible to render, block render, component metadata, and static validation. Nested defs are not render-block targets and cannot be validated reliably.

Security Errors (K-SEC-xxx)

Security errors occur in sandboxed environments when a template tries to access restricted resources.

k-sec-001

Blocked attribute — Access to an attribute was denied by the sandbox policy.

Fix: Check theSandboxPolicy.allowed_attributesconfiguration. Add the attribute if it should be accessible, or access the data through a different path.

k-sec-002

Blocked type — An object type is not allowed in the sandbox.

Fix: Check theSandboxPolicy.blocked_typesconfiguration. Remove the type from the blocked list if it should be allowed, or pass only supported types in the render context.

k-sec-003

Range limit exceeded — Arange()call exceeded the sandbox's maximum allowed range size.

Fix: Reduce the range size or increaseSandboxPolicy.max_range.

k-sec-004

Blocked callable — A function or method call was denied by the sandbox policy.

Fix: Check theSandboxPolicy.allow_callingconfiguration. If calling is required, enable it only for trusted templates, or use a filter instead of calling methods directly.

k-sec-005

Output limit exceeded — Rendered output exceededSandboxPolicy.max_output_size.

Fix: Reduce template output size or increaseSandboxPolicy.max_output_size. Consider paginating large datasets.

Component Validation (K-CMP-xxx)

Component validation diagnostics are emitted byEnvironment(validate_calls=True) andkida check --validate-calls. They are compile-time diagnostics for {% def %} call sites, including calls to literal {% from "..." import ... %} component imports. Dynamic imports are skipped because Kida cannot know the target template at check time.

k-cmp-001

Component call signature mismatch — A component call used unknown keyword arguments, omitted required parameters, or supplied duplicate keyword arguments.

Fix: Compare the call site with the component's{% def %}signature. Rename misspelled props, add missing required props, or remove props the component does not accept.

Example:

{% def card(title: str) %}{{ title }}{% end %}
{{ card(titl="Settings") }}

Use title= instead of titl=.

k-cmp-002

Component literal type mismatch — A literal argument does not match the component parameter annotation. Kida validates literalstr, int, float, bool, None, and simple |unions. Variable arguments and custom types are documentary and skipped.

Fix: Pass a literal with the annotated type, update the annotation if the component accepts both shapes, or move validation into Python when the value is dynamic.

Example:

{% def badge(count: int) %}{{ count }}{% end %}
{{ badge("five") }}

Pass 5or change the parameter type if string counts are intentional.

Warnings (K-WARN-xxx)

Compile-time warnings that indicate potential issues but do not prevent rendering.

k-warn-001

Filter precedence — The filter pipe| binds tighter than the null coalescing operator ??. This means x ?? [] | length is parsed as x ?? ([] | length), which applies the filter only to the fallback, not the full expression.

Fix: Add parentheses to clarify intent:(x ?? []) | length.

k-warn-002

Jinja2set scoping difference — A nested {% set x = ... %} targets a name already bound template-wide via {% let x %} or {% export x %}. In Kida this creates a block-scoped shadow that does not leak to outer scope; in Jinja2 it would modify the outer variable.

Fix: Use{% export x = ... %}to write to outer scope, or rename the target to avoid the shadow.

Enabled by default. Suppress withwarnings.filterwarnings("ignore", category=MigrationWarning) or Environment(jinja2_compat_warnings=False). The warning is narrowed to the actual trap pattern — fresh names used for genuine block-scoped work do not trigger.

See Also

  • Error Handling — Exception types, format_compact(), SourceSnippet
  • [Undefined Variable] — Debugging K-RUN-001
  • [Template Not Found] — Debugging K-TPL-001