Introduction
Ansible evaluates Jinja2 expressions before it can render templates or run many tasks. If a variable does not exist for one host, group, or environment, the playbook stops with an undefined variable error even though it may work perfectly for other hosts. The right fix is to understand why the variable is missing, not to blindly wrap every expression in fallbacks.
Symptoms
- The playbook fails with
AnsibleUndefinedVariable - One inventory group succeeds while another fails on the same template
- A dictionary key such as
app.portexists for some hosts but not others - Recent inventory or role refactors introduced a variable lookup error
Common Causes
- A variable is defined only in one inventory group or host file
- The template assumes a nested key exists for every host
- Role defaults, vars, and extra-vars precedence were misunderstood
- Strict or defensive template rendering exposed previously hidden inventory gaps
Step-by-Step Fix
- 1.Reproduce the failure with verbose output and inspect the missing variable
- 2.Start by identifying the exact expression and host context instead of changing the whole template blindly.
ansible-playbook site.yml -vvv- 1.Trace the variable through inventory, role defaults, and host vars
- 2.Confirm whether the value should come from
group_vars,host_vars, role defaults, or extra-vars. Many failures happen because the variable exists, just not in the current host scope.
- debug:
var: app_port- 1.**Use
defaultoris definedonly where a missing value is actually acceptable** - 2.Optional values should have explicit fallbacks. Required values should fail clearly instead of producing a silently broken configuration.
```yaml listen_port: {{ app_port | default(8080) }}
{% if tls_cert_path is defined %} ssl_certificate {{ tls_cert_path }}; {% endif %} ```
- 1.Add early validation for truly required variables
- 2.If a playbook cannot succeed without a variable, fail early with
assertso the error is obvious before template rendering reaches a deeper task.
- assert:
that:
- db_host is defined
- db_user is defined
- db_password is definedPrevention
- Keep required variables documented per role and environment
- Use role defaults for safe optional settings, not for secrets or environment-specific values
- Validate inventory changes in CI before deploying to real hosts
- Prefer explicit
is definedchecks over assuming every nested key exists