AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Template Error While Templating String: Fix Every Jinja2 Error

By Luca Berton · Published 2024-01-01 · Category: installation

Fix every Ansible 'template error while templating string' with 15+ real examples. Covers undefined variables, type errors, missing filters, nested quotes.

"An error occurred while templating string" is the most common Jinja2 error in Ansible. The message is frustratingly vague — the actual cause could be undefined variables, type mismatches, bad syntax, or a dozen other things. This guide covers every variant with the exact fix.

Error Format

fatal: [host]: FAILED! => {
    "msg": "An error occurred while templating string:
    {{ some_expression }}. Error was a <class 'ansible.errors.AnsibleUndefinedVariable'>,
    original message: 'variable_name' is undefined"
}

The key is the original message at the end — that tells you the real problem.

See also: Ansible Troubleshooting Installation Issues on macOS and Python

Error 1: Variable Is Undefined

Error

'my_variable' is undefined

Cause and Fix

# ❌ Variable doesn't exist
- ansible.builtin.debug:
    msg: "{{ my_variable }}"

# ✅ FIX 1: Define the variable - hosts: all vars: my_variable: "hello"

# ✅ FIX 2: Use default filter - ansible.builtin.debug: msg: "{{ my_variable | default('fallback') }}"

# ✅ FIX 3: Check before using - ansible.builtin.debug: msg: "{{ my_variable }}" when: my_variable is defined

Error 2: Attribute Not Found on Dict

Error

'dict object' has no attribute 'nonexistent_key'

Cause and Fix

# ❌ Key doesn't exist in the dict
- ansible.builtin.debug:
    msg: "{{ result.json.status }}"
  # result.json doesn't have a 'status' key

# ✅ FIX 1: Use default - ansible.builtin.debug: msg: "{{ result.json.status | default('unknown') }}"

# ✅ FIX 2: Use bracket notation with default - ansible.builtin.debug: msg: "{{ result.json['status'] | default('unknown') }}"

# ✅ FIX 3: Debug the actual structure first - ansible.builtin.debug: var: result.json

See also: Ansible Conflicting Action Statements Error: Causes and Fixes

Error 3: String Cannot Be Converted to Int/Float

Error

could not convert string to float: 'not_a_number'

Cause and Fix

# ❌ Comparing string to int
- ansible.builtin.assert:
    that: result.stdout > 100
  # result.stdout is always a string

# ✅ FIX: Cast explicitly - ansible.builtin.assert: that: result.stdout | int > 100

# ✅ For float comparison - ansible.builtin.assert: that: result.stdout | float > 99.5

Error 4: Nested Quoting Issues

Error

unexpected char '#' at ...
template error while templating string

Cause and Fix

# ❌ YAML/Jinja2 quote collision
- ansible.builtin.debug:
    msg: "{{ 'hello "world"' }}"

# ✅ FIX 1: Alternate quotes - ansible.builtin.debug: msg: "{{ 'hello \"world\"' }}"

# ✅ FIX 2: Use YAML literal block - ansible.builtin.debug: msg: >- {{ 'hello "world"' }}

# ❌ Hash in string looks like YAML comment - ansible.builtin.debug: msg: "Color is {{ color }} #ffffff"

# ✅ FIX: Quote the whole thing - ansible.builtin.debug: msg: "Color is {{ color }} {{ '#ffffff' }}"

See also: Ansible Permission Denied on Remote Temp Path: Fix Every Cause

Error 5: Filter Not Found

Error

No filter named 'community.general.json_query'

Cause and Fix

# json_query requires jmespath
pip install jmespath

# Or in requirements.txt pip install jmespath ansible

# Some filters require collections
# Install the collection first:
# ansible-galaxy collection install community.general

- ansible.builtin.debug: msg: "{{ data | community.general.json_query('servers[*].name') }}"

Error 6: Recursive Templating

Error

recursive loop detected in template string

Cause and Fix

# ❌ Variable references itself
vars:
  my_url: "https://{{ my_url }}/api"

# ✅ FIX: Use different variable names vars: base_url: "https://example.com" api_url: "{{ base_url }}/api"

Error 7: Type Error in Filter

Error

'NoneType' object is not iterable

Cause and Fix

# ❌ Filtering a None/undefined value
- ansible.builtin.debug:
    msg: "{{ missing_list | join(', ') }}"

# ✅ FIX: Default to empty list - ansible.builtin.debug: msg: "{{ missing_list | default([]) | join(', ') }}"

# ✅ For dict operations - ansible.builtin.debug: msg: "{{ missing_dict | default({}) | dict2items }}"

Error 8: Boolean Expression Issues

Error

Conditional check '...' failed. The error was: ...

Cause and Fix

# ❌ String treated as boolean
- ansible.builtin.debug:
    msg: "enabled"
  when: some_var    # some_var might be the string "false"

# ✅ FIX: Explicit bool conversion when: some_var | bool

# ❌ Comparing to string "true" when: some_var == true # Fails if some_var is "true" (string)

# ✅ FIX when: some_var | bool == true

Error 9: Whitespace in Jinja2

Error

expected token 'end of statement block', got 'string'

Cause and Fix

# ❌ Missing spaces around operators
- ansible.builtin.debug:
    msg: "{{ var1+var2 }}"

# ✅ FIX: Add spaces - ansible.builtin.debug: msg: "{{ var1 + var2 }}"

# ❌ Extra braces - ansible.builtin.debug: msg: "{{{ variable }}}"

# ✅ FIX - ansible.builtin.debug: msg: "{{ variable }}"

Error 10: YAML Multiline String Issues

Error

could not find expected ':'

Cause and Fix

# ❌ Jinja2 in unquoted YAML value that starts with {
  vars:
    value: {{ something }}

# ✅ FIX: Always quote Jinja2 expressions vars: value: "{{ something }}"

# ❌ Multiline template with bad indentation msg: "{{ items | join(', ') }}"

# ✅ FIX: Use YAML multiline scalar msg: >- {{ items | join(', ') }}

Error 11: ansible-core 2.19 Strict Templating

New in ansible-core 2.19 — stricter Jinja2 evaluation:

# ❌ BREAKS in 2.19 — truthy string in conditional
  when: some_string_variable

# ✅ FIX: Explicit boolean test when: some_string_variable | length > 0

# ❌ BREAKS in 2.19 — implicit truth test when: result.stdout

# ✅ FIX when: result.stdout | length > 0 # or when: result.stdout != ""

See ansible-core 2.19 Templating Changes for the full list.

Debugging Tips

# 1. Enable verbose mode
ansible-playbook site.yml -vvv

# 2. Test expressions interactively ansible localhost -m debug -a "msg={{ 'hello' | upper }}"

# 3. Dump all variables for a host ansible host -m debug -a "var=hostvars[inventory_hostname]"

# 4. Use the 'type_debug' filter - ansible.builtin.debug: msg: "{{ my_var | type_debug }}" # Shows: "str", "list", "dict", "NoneType", etc.

FAQ

How do I find which line causes the template error?

Use -vvv to see the full traceback. The error message includes the template string that failed. Search your playbook for that exact string. In roles, check defaults/main.yml and vars/main.yml for the variable definition.

Why does my template work in one play but fail in another?

Variables are scoped. A variable set in play 1 (via vars:) isn't available in play 2. Use set_fact (persists across plays), group_vars (inventory-level), or extra_vars (global) for cross-play variables.

How do I escape Jinja2 syntax in a template file?

Use {% raw %}...{% endraw %} to output literal {{ }} in template files:

{% raw %}
This {{ will not be templated }}
{% endraw %}

Can I test Jinja2 expressions without running a playbook?

Yes. Use ansible localhost -m debug -a "msg={{ expression }}" for quick tests, or ansible-playbook --check for full playbook validation without making changes.

Conclusion

Every Ansible template error traces back to: undefined variables (use default), type mismatches (use int/float/bool filters), quoting issues (always quote {{ }}), or missing dependencies (jmespath for json_query). Read the original message at the end of the error — it tells you exactly what went wrong.

Related Articles

ansible-core 2.19 Templating ChangesAnsible Undefined Variable Error: 12 FixesAnsible Jinja2 Filters ReferenceAnsible default() Filter Guide

See also

Fix Ansible "undefined variable" Error: Variable Scope and Precedence

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home