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.
{# Start here #}
{{ states('sensor.outdoor_temperature') }}
22.5
{# Add the conversion #}
{{ states('sensor.outdoor_temperature') | float(0) }}
22.5
{# Add the rounding #}
{{ states('sensor.outdoor_temperature') | float(0) | round(1) }}
22.5
{# Add the full sentence #}
It is {{ states('sensor.outdoor_temperature')
| float(0) | round(1) }}°C outside.
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.
{{ states('sensor.outdoor_temperature') }}
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:
{{ states('sensor.outdoor_temperature') | typeof }}
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:
{{ state_attr('media_player.living_room', 'source_list') | tojson }}
["Spotify", "Bluetooth", "TV", "Radio"]
Or list every attribute:
{% for key, value in states.media_player.living_room.attributes.items() %}
{{ key }}: {{ value }}
{% endfor %}
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
- 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. - 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
- Make sure the result of the template is false, for example, by changing the state that the template checks.
- 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
unknownorunavailable. Add a fallback with| default(...)or anif 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'isFalsebecause 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. -
Nonemust be capitalized. Python writesNone,True,Falsewith a capital first letter. Template tests and literals use lowercasenone,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
whileloops. Templates only supportforloops. -
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 anamespaceinstead.
Next steps
- Looking up a specific error message? See Error messages and fixes.
- Need a working example to compare against? Browse Common template patterns.
- Want to refresh the basics? Review Template syntax.
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).
AI assistants like ChatGPT or Claude can also explain or fix templates when you describe what you want in plain language.