Debugging templates

Every template author has stared at a template that refuses to work and wondered if they’re losing it. You are not. Templates are fiddly, and even experienced people make the same mistakes over and over. This page walks through the tools and habits that turn “why isn’t this working?” into “ah, that’s the problem”.

The template editor

Home Assistant has a built-in template editor that shows the result of a template while you type. Open it from Settings > Tools > Template.

The editor is the fastest feedback loop you have. It:

  • Shows the output of your template live.
  • Points at errors with a red message.
  • Has access to all your entities, which means you can try the template against real data.

When a template misbehaves in an automation or template entity, copy it into the editor, adjust until it produces what you want, then paste it back.

Read the error message

When a template has a mistake, Home Assistant shows an error. The message is often more helpful than it looks.

UndefinedError: 'foo' is undefined Something in your template refers to a variable that does not exist. Check the spelling and make sure anything you {% set %} is defined before you use it.

TypeError: unsupported operand type(s) You are trying to do something to a value of the wrong type, like adding a number to some text. Convert with float or int first, and remember to add a fallback.

TemplateSyntaxError A typo in the template itself. Count your brackets, check that every {% if %} has an {% endif %}, and that every {% for %} has an {% endfor %}.

No first item, sequence was empty You used first or last on an empty list. Add an if check, or use the default filter.

Narrow down the problem

When a long template does not work, the trick is to take it apart. Start with the smallest piece you can and add one thing at a time. The moment the result goes wrong, you know exactly which piece broke. This sounds slow but it is always faster than staring at the whole thing and hoping the problem jumps out.

TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{# Start here #}
{{ states('sensor.outdoor_temperature') }}
Result
22.5
TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{# Add the conversion #}
{{ states('sensor.outdoor_temperature') | float(0) }}
Result
22.5
TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{# Add the rounding #}
{{ states('sensor.outdoor_temperature') | float(0) | round(1) }}
Result
22.5
TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{# Add the full sentence #}
It is {{ states('sensor.outdoor_temperature')
         | float(0) | round(1) }}°C outside.
Result
It is 22.5°C outside.

Check what a value actually is

When a template gives the wrong result, show the raw value to see what you are working with.

TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{{ states('sensor.outdoor_temperature') }}
Result
22.5

That result looks like a number, but it is actually text. Many sensors return text even when the content looks numeric. Use typeof to be sure:

TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{{ states('sensor.outdoor_temperature') | typeof }}
Result
str

str is short for “string”, which is how templates refer to text. If you see str where you expected a number, that’s your clue to convert with float or int. int and float in the output mean the value is already a whole number or decimal number.

Inspect attributes

When you are not sure what attributes an entity has, show them all with tojson:

TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{{ state_attr('media_player.living_room', 'source_list') | tojson }}
Result
["Spotify", "Bluetooth", "TV", "Radio"]

Or list every attribute:

TemplateA template is an automation definition that can include variables for the action or data from the trigger values. This allows automations to generate dynamic actions. [Learn more]
{% for key, value in states.media_player.living_room.attributes.items() %}
  {{ key }}: {{ value }}
{% endfor %}
Result
friendly_name: Living room
volume_level: 0.35
source: Spotify
source_list: ['Spotify', 'Bluetooth', 'TV', 'Radio']

When does my template run?

A common source of confusion is “why isn’t my template updating?”, or the opposite: “why is it running so often?”. Home Assistant decides when to re-evaluate a template based on what is inside it.

Entity states. When your template reads a state, like states('sensor.temperature'), Home Assistant watches that entity. The template runs again every time the entity’s state changes.

now() and utcnow(). Templates that use now() or utcnow() re-run once per minute.

Other variables. Templates that depend on this, trigger, or other context variables only re-run when the context changes (a new trigger fires, the entity updates).

If you write a template that does not read any state or use now(), it runs once at startup and never again. That is fine for constant values, but it’s a common trap when you want a template to react to something.

Why does my template behave differently in Tools?

The Template editor shows the result of your template right away. It updates the result while you type, and when the states that the template uses change. That makes it great for testing, but the editor does not run your template the same way as an automation or a template entity. A template can work in the editor and not in your automation, or the other way around.

Template with this or trigger shows an error or an empty result in the editor

Symptom 1

Your template uses this or trigger, for example, {{ trigger.to_state.state }}. In the Template editor, it shows an error, or a warning and an empty result.

Cause

The editor does not have the variables this and trigger. Home Assistant only provides them when the template runs in certain places, such as an automation or a template entity.

Resolution

  1. In the Template editor, at the top of the template, define the variables yourself with {% set %}, using the values you expect. For an example, refer to testing an incoming-data template.
  2. Check the result.
    • Result: The editor shows the result that the template gives with these values.
Template trigger does not react

Symptom 2

In the Template editor, the result of your template is true, but the automation with the template trigger does not start.

Cause

A template trigger only reacts when the result of the template changes from false to true. The editor only shows the current result. If the result is already true when you load the automation, the trigger does not react until the result has been false again.

Resolution

  1. Make sure the result of the template is false, for example, by changing the state that the template checks.
  2. Cause the change that makes the result true.
    • Result: The trigger reacts, and the automation starts.

Common mistakes

  • Sensor gives text, not a number. Use | float(0) or | int(0).
  • Entity is unknown or unavailable. Add a fallback with | default(...) or an if has_value(...) check.
  • Variable changes inside a loop are lost. Use namespace.
  • YAML refuses to load your template. Check quoting. See Templates in YAML.
  • Template appears as literal text in output. The field does not support templating, or the template is inside a {% raw %} / {% endraw %} block.
  • Template evaluates at the wrong time. Triggers and conditions are checked on change, not continuously. A template condition that depends on now() only re-checks when something else triggers.
  • Comparing text to a number. '6' < '10' is False because text is compared alphabetically, not numerically. Convert with | float(0) or | int(0) on both sides first.

Common Python mistakes

Templates use Jinja2, a templating engine built on top of Python, but the syntax is not the same as Python. A few things that work in Python don’t work in templates:

  • No print(). Write {{ expression }} to show a value. There is no print statement.
  • No import. You cannot import modules. The functions available to you are the ones in the template functions reference plus the standard Jinja filters.
  • No = inside {{ }} for assignment. Use {% set name = value %} to create a variable. Inside {{ }}, = does not exist.
  • None must be capitalized. Python writes None, True, False with a capital first letter. Template tests and literals use lowercase none, true, false. Both work in most places, but be consistent.
  • No f-strings. Python’s f"hello {name}" is not template syntax. Use "hello " ~ name (the ~ joins text) or {{ name }} directly.
  • No while loops. Templates only support for loops.
  • List and dict methods are limited. Read-only methods like .items(), .values(), .keys(), .get(), .split(), .lower(), and .upper() work fine. Methods that mutate a value in place, like .append(), .pop(), or .update(), are blocked as unsafe. To build up a list across loop iterations, use a namespace instead.

Next steps

Still stuck?

The Home Assistant community is quick to help: join Discord for real-time chat, post on the community forum with your template and expected result, or share on our subreddit. When you ask, include these four things and the answer usually comes within minutes:

  • The template you are using (copied from the editor, where you can see what it runs against).
  • What you expected the result to be.
  • What the actual result or error was.
  • The entity IDs involved (from Settings > Tools > States).

Tip

AI assistants like ChatGPT or Claude can also explain or fix templates when you describe what you want in plain language.