Introduction

Writing efficient conditional logic in Ansible often means leveraging Jinja2 templating. One particularly powerful feature is the ternary operator, which helps you choose between two values based on a condition. However, many users encounter the dreaded error:

``

template error while templating string: unexpected character

`

This article walks through the correct way to use ternary expressions in Ansible using Jinja2 filters and shows how to avoid common pitfalls.

The Problem: Using JavaScript-style Ternary in Ansible

If you've ever written something like this in your Ansible playbook or template:

`jinja2

{{ env == 'dev' ? 'localhost' : 'db.prod.internal' }}

`

You’ve likely been met with a syntax error. That’s because Jinja2 does not support this JavaScript-style ternary operator. Instead, Ansible uses a different syntax via the ternary filter.

The Correct Way: Use the ternary Filter

To properly use conditional logic in Ansible, wrap your condition in parentheses and apply the ternary() filter:

`jinja2

{{ (env == 'dev') | ternary('localhost', 'db.prod.internal') }}

`

This line says: if env is 'dev', return 'localhost'; otherwise, return 'db.prod.internal'.

Example Use Case in a Template

Suppose you’re building an .env.j2 file and want to set the database host depending on the environment:

`jinja2

DB_HOST={{ (env | default('prod')) == 'dev' | ternary('localhost', 'db.prod.internal') }}

`

This ensures the condition works even if env isn’t defined.

Common Mistakes and Fixes

| Mistake | Why it's wrong | Correct Syntax |

|--------|----------------|----------------|

| env == 'dev' ? 'a' : 'b' | Not valid Jinja2 | (env == 'dev') | ternary('a', 'b') |

| Missing parentheses | Jinja2 parses it incorrectly | Always use parentheses around the condition |

| Forgetting | before ternary | ternary is a filter, not a function | Use | ternary(...) |

Debugging Tips

  • Use debug tasks to check expressions:

`yaml

- debug:

msg: "{{ (my_var is defined) | ternary(my_var, 'default') }}"

`

  • Pipe | type_debug to see what kind of data you're working with.

Why Use Ternary?

The ternary operator in Jinja2 helps you:

  • Avoid verbose if-else blocks in templates.
  • Keep playbooks and configuration files cleaner.
  • Make conditional assignments more readable.

Conclusion

When used correctly, the ternary operator can drastically improve the clarity and maintainability of your Ansible playbooks and templates. Avoid syntax errors by remembering: wrap the condition in parentheses and use the | ternary(true_value, false_value) filter. Stick to this structure, and you’ll avoid the classic unexpected character` template error for good.