TL;DR: The Quick Fix
This error is almost always caused by a syntax typo in your Jinja2 expression. The most common culprit is a missing closing brace } or a malformed inline if/else statement.
Check the line mentioned in the error and ensure your variable looks like this:
# Wrong
msg: "{{ myvar }"
# Right
msg: "{{ myvar }}"
If you are using an inline conditional, ensure you have both if and else:
# Wrong (missing else)
msg: "{{ 'active' if enabled }}"
# Right
msg: "{{ 'active' if enabled else 'inactive' }}"
The Root Cause
Ansible uses the Jinja2 templating engine to evaluate everything inside {{ ... }}. When you see expected token ':', got '}', it means the Jinja2 parser was expecting a specific character to follow your variable or expression, but it hit a closing brace (or the end of the string) instead.
The parser gets "confused" depending on the context. For example, if it thinks you are starting a dictionary mapping or a ternary-style operation, it looks for a colon :. If you provide a single } instead of the expected }}, the parser fails because the expression is syntactically incomplete.
Common Scenarios and Fixes
1. The Missing Brace (The Typo)
This is the most frequent cause. You start a variable with {{ but only close it with a single }.
# Fails with: expected token ':', got '}'
- name: Print a variable
ansible.builtin.debug:
msg: "The value is {{ web_server_port }"
The Fix: Always ensure you have matching pairs of double braces.
- name: Print a variable
ansible.builtin.debug:
msg: "The value is {{ web_server_port }}"
2. Incomplete Inline Ternary Expressions
Jinja2 supports value_if_true if condition else value_if_false. Unlike some other languages, the else part is mandatory in Jinja2 expressions when used inside {{ ... }}.
# Fails
- name: Set status
ansible.builtin.set_fact:
app_status: "{{ 'running' if service_up }}"
The Fix: Add the else clause.
- name: Set status
ansible.builtin.set_fact:
app_status: "{{ 'running' if service_up else 'stopped' }}"
3. Improper Quoting in YAML
Sometimes the YAML parser and the Jinja2 parser clash. If your string starts with {{, YAML requires the entire line to be quoted. If you miss the quotes or use them incorrectly, the Jinja2 string passed to the engine might be truncated or mangled.
# Might cause issues
- name: Incorrect quoting
shell: echo {{ my_var }
The Fix: Always quote your Jinja2 expressions when they are the start of a value.
- name: Correct quoting
shell: "echo {{ my_var }}"
4. Dictionary Syntax Inside Expressions
If you are trying to access a dictionary key or define a dictionary on the fly, a missing colon or quote will trigger this error.
# Fails if you forget the colon in a dict
- name: Buggy dict access
ansible.builtin.set_fact:
config: "{{ {'port' 8080} }}" # Missing colon after 'port'
Verification Steps
To confirm the fix, run your playbook with the syntax check flag. This is faster than running the whole deployment.
ansible-playbook my_playbook.yml --syntax-check
If the syntax check passes, use the debug module to verify the expression renders correctly:
- name: Debugging the fix
ansible.builtin.debug:
msg: "Variable is: {{ myvar }}"
Pro-Tips for Prevention
- Use an IDE extension: VS Code with the "Ansible" or "Jinja2" extension will highlight mismatched braces in red.
- Spaces matter for readability: Use
{{ variable }}instead of{{variable}}. It makes it much easier to spot a missing brace at the end. - Linter: Run
ansible-lint. It often catches these low-level syntax errors before you even try to run the code.

