Undefined Variable

Debug undefined variable errors

3 min read 540 words

DebugUndefinedErrorexceptions.

The Error

UndefinedError: Undefined variable 'usre' in page.html:5

Common Causes

Solutions

Use default Filter

{{ user.nickname | default("Anonymous") }}
{{ config.timeout | default(30) }}

Check with is defined

Theis defined test works on attribute chains, not just top-level variables. If any part of the chain is missing, the result is undefined:

{% if user is defined %}
    {{ user.name }}
{% else %}
    Guest
{% end %}

Attribute Chains

{# Checks if pokemon has a "name" attribute — not just if pokemon exists #}
{% if pokemon.name is defined %}
    {{ pokemon.name }}
{% end %}

{# Works with dict keys too #}
{% if settings.theme is defined %}
    Theme: {{ settings.theme }}
{% end %}

{# Deep chains #}
{% if page.author.avatar is defined %}
    <img src="{{ page.author.avatar }}">
{% end %}

Undefined Sentinel

Missing attribute access returns an_Undefinedsentinel (not an empty string). The sentinel is:

  • Falsy{% if pokemon.name %}works as a guard
  • Stringifies to""{{ pokemon.name }}renders nothing when undefined
  • Iterable — yields nothing, so{% for x in missing_attr %}produces no output

Theis defined and is undefined tests work correctly on attribute chains (e.g. {% if pokemon.name is defined %}), making intent explicit. See Tests Reference for the full test list.

Optional Chaining Pattern

{% if post and post.author %}
    {{ post.author.name }}
{% end %}

Safe Navigation

{{ user | default({}) | attr("name") | default("Unknown") }}

Debug Tips

# In Python
print(context.keys())

Use debug Filter

{{ user | debug }}

Output (to stderr):

DEBUG: <User>
  .name = 'Alice'
  .email = 'alice@example.com'

Check Template Context

def render_debug(template_name, **context):
    print(f"Rendering {template_name}")
    print(f"Context keys: {list(context.keys())}")
    return env.render(template_name, **context)

Prevention

Type Hints for Context

from dataclasses import dataclass

@dataclass
class PageContext:
    title: str
    user: User
    items: list[Item]

# IDE will catch missing fields
context = PageContext(title="Hello", user=user, items=items)
template.render(**asdict(context))

Template Validation

def validate_context(context, required):
    missing = [k for k in required if k not in context]
    if missing:
        raise ValueError(f"Missing: {missing}")

See Also