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.

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

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

How to fix Ansible undefined variable error. Understand variable scope, precedence, default values, and common causes. Complete troubleshooting guide.

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

The "undefined variable" error is one of the most common Ansible issues. It means a variable is referenced but hasn't been defined in the current scope.

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

Common Causes

1. Variable Not Defined

# ❌ Error: 'app_version' is undefined
- name: Deploy app
  ansible.builtin.debug:
    msg: "Deploying {{ app_version }}"

# ✅ Fix: Define the variable - hosts: webservers vars: app_version: "2.1.0" tasks: - name: Deploy app ansible.builtin.debug: msg: "Deploying {{ app_version }}"

2. Typo in Variable Name

vars:
  database_host: db.example.com

tasks: # ❌ Typo: databse_host - ansible.builtin.debug: msg: "{{ databse_host }}"

# ✅ Correct spelling - ansible.builtin.debug: msg: "{{ database_host }}"

3. Variable from Another Host

# ❌ Can't access another host's registered variable directly
- hosts: databases
  tasks:
    - ansible.builtin.command: pg_isready
      register: db_status

- hosts: webservers tasks: # This fails — db_status is on database hosts - ansible.builtin.debug: msg: "{{ db_status }}"

# ✅ Fix: Use hostvars - ansible.builtin.debug: msg: "{{ hostvars['db01']['db_status'] }}"

4. Conditional Variable

# ❌ Variable only defined in one branch
- ansible.builtin.set_fact:
    result: success
  when: some_condition

- ansible.builtin.debug: msg: "{{ result }}" # Fails if some_condition was false

# ✅ Fix: Use default filter - ansible.builtin.debug: msg: "{{ result | default('not set') }}"

Best Practices to Prevent Undefined Variables

# 1. Always use defaults
"{{ my_var | default('fallback_value') }}"
"{{ my_list | default([]) }}"
"{{ my_dict | default({}) }}"

# 2. Use default(omit) for optional parameters - ansible.builtin.user: name: "{{ user_name }}" groups: "{{ user_groups | default(omit) }}"

# 3. Validate inputs with assert - ansible.builtin.assert: that: - app_version is defined - env is defined fail_msg: "Required variables not set"

# 4. Set role defaults # roles/myrole/defaults/main.yml app_port: 8080 app_env: production log_level: info

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

FAQ

Why does Ansible say my variable is undefined?

The variable hasn't been defined in the current scope — it may be missing from vars, inventory, var files, or not passed via -e. Check spelling, scope (host vs play), and variable precedence.

How do I set a default value for undefined variables?

Use the default Jinja2 filter: {{ my_var | default('fallback') }}. This returns 'fallback' if my_var is not defined.

How do I check if a variable is defined?

Use when: my_var is defined in conditionals, or {{ my_var | default(omit) }} to skip optional parameters entirely.

Related Articles

Ansible Variables: Complete GuideAnsible Facts GuideAnsible Playbook Guide

See also: Ansible Template Error While Templating String: Fix Every Jinja2 Error

Variable Precedence Order

Ansible has 22 levels of variable precedence. Here are the most commonly used (highest wins):

| Priority | Source | Example | |---|---|---| | 1 (highest) | Extra vars (-e) | ansible-playbook -e "var=value" | | 2 | Task vars | vars: in a task | | 3 | Block vars | vars: in a block | | 4 | Role/include params | roles: - role: x, var: val | | 5 | Play vars | vars: in a play | | 6 | Host vars (inventory) | host_vars/hostname.yml | | 7 | Group vars (inventory) | group_vars/groupname.yml | | 8 (lowest) | Role defaults | roles/x/defaults/main.yml |

Safe Variable Access with Defaults

# Use the default filter to avoid undefined errors
- name: Safe variable access
  ansible.builtin.debug:
    msg: "Value: {{ my_var | default('fallback_value') }}"

# Use mandatory filter to fail with clear message - name: Require a variable ansible.builtin.debug: msg: "Value: {{ required_var | mandatory }}"

# Check if variable is defined - name: Conditional on variable ansible.builtin.debug: msg: "Variable is: {{ optional_var }}" when: optional_var is defined

Common Causes and Fixes

# ❌ Variable defined in one play, used in another
- hosts: webservers
  tasks:
    - ansible.builtin.set_fact:
        my_result: "done"

- hosts: dbservers tasks: - ansible.builtin.debug: msg: "{{ my_result }}" # UNDEFINED!

# ✅ Use hostvars to access cross-host variables - hosts: dbservers tasks: - ansible.builtin.debug: msg: "{{ hostvars['web01']['my_result'] }}"

FAQ

Why is my variable undefined when I defined it in another play?

Variables set with set_fact or register are scoped to the host they run on. To access them from another host, use hostvars['hostname']['variable_name'].

How do I set a global variable accessible everywhere?

Use extra vars (-e), or define the variable in group_vars/all.yml which applies to every host.

What is the difference between vars and defaults in roles?

defaults/main.yml has the lowest precedence — easily overridden by anything. vars/main.yml has higher precedence and is harder to override. Use defaults for values users should customize.

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home