Fix Ansible Jinja2 "UndefinedError"
The Error
fatal: [webserver]: FAILED! => {
"msg": "The task includes an option with an undefined variable.
The error was: 'my_variable' is undefined"
}
Solution 1: Use the default Filter
# Provide a fallback value
- debug:
msg: "Port is {{ http_port | default(8080) }}"
# Default to empty string
- debug:
msg: "Optional: {{ optional_var | default('') }}"
# Default to omit (skip the parameter entirely)
- ansible.builtin.user:
name: deploy
groups: "{{ extra_groups | default(omit) }}"
Solution 2: Check Before Using
- debug:
msg: "Value: {{ my_var }}"
when: my_var is defined
- debug:
msg: "Not set"
when: my_var is not defined
Solution 3: Set Variable Defaults in Role
# roles/myrole/defaults/main.yml
http_port: 8080
enable_ssl: false
app_user: www-data
Solution 4: Use vars with Defaults
- hosts: webservers
vars:
http_port: "{{ custom_port | default(80) }}"
app_env: "{{ environment | default('production') }}"
tasks:
- debug:
msg: "Running on port {{ http_port }} in {{ app_env }}"
Solution 5: Make Variables Mandatory
# Fail fast with a clear message
- assert:
that:
- database_host is defined
- database_password is defined
fail_msg: "database_host and database_password must be defined"
# Or use mandatory filter
- debug:
msg: "DB: {{ database_host | mandatory }}"
Common Causes
Variable Scope Issues
# Variable set in one play is NOT available in another
- hosts: db
tasks:
- set_fact:
db_ip: "{{ ansible_default_ipv4.address }}"
- hosts: web
tasks:
# WRONG — db_ip is not in scope
- debug:
msg: "{{ db_ip }}"
# RIGHT — access from the other host
- debug:
msg: "{{ hostvars['db']['db_ip'] }}"
Typos
# Check your variable names carefully
- debug:
msg: "{{ http_prot }}" # ← typo! should be http_port
Missing group_vars/host_vars
# Make sure the file exists and is valid YAML
cat inventory/group_vars/webservers.yml
Conclusion
Always use | default() for optional variables. Use is defined checks for conditional logic. Set defaults in roles/*/defaults/main.yml for role variables.