Introduction

The literal-compare rule (601) in ansible-lint flags redundant comparisons to True or False in when conditions. While technically correct, these comparisons add noise without value — and can introduce subtle bugs with string-to-boolean conversion.

The Error

# ⚠️ Triggers literal-compare warning
- name: Run only in production
  ansible.builtin.debug:
    msg: "Production task"
  when: production == True
$ ansible-lint playbook.yml
literal-compare: Don't compare to literal True/False.
playbook.yml:5 Task/Handler: Run only in production

The Fix

# ✅ Clean — directly evaluate the boolean
- name: Run only in production
  ansible.builtin.debug:
    msg: "Production task"
  when: production

For negative conditions:

# ❌ Redundant
when: debug_mode == False

# ✅ Clean
when: not debug_mode

Why It Matters

1. Readability

# Verbose and redundant
when: is_enabled == True and is_configured == True

# Clear and concise
when: is_enabled and is_configured

2. Avoid String/Boolean Bugs

Variables from inventory or extra-vars may be strings, not booleans:

ansible-playbook site.yml -e "production=true"
# production is the STRING "true", not boolean True
# ⚠️ BUG: "true" (string) != True (boolean)
when: production == True  # This is FALSE!

# ✅ Works: Jinja2 evaluates "true" as truthy
when: production

# ✅ Safest: explicitly convert to bool
when: production | bool

3. Consistency

Following lint rules ensures all team members write conditions the same way.

Common Patterns

Simple Boolean

# ❌ Don't
when: enable_ssl == True
when: enable_ssl == False

# ✅ Do
when: enable_ssl
when: not enable_ssl

Boolean with bool Filter

# When variable might be a string ("true"/"false"/"yes"/"no")
when: enable_feature | bool
when: not (skip_tests | bool)

Compound Conditions

# ❌ Don't
when: is_production == True and ssl_enabled == True

# ✅ Do
when: is_production and ssl_enabled

# ✅ With bool filter for safety
when: is_production | bool and ssl_enabled | bool

Comparing to Specific Values (NOT Affected)

These are fine — the rule only applies to True/False literals:

# ✅ These are legitimate comparisons
when: env == "production"
when: ansible_os_family == "RedHat"
when: count | int > 5
when: status == "active"

Testing for None/Undefined

# ✅ Check if defined
when: my_var is defined

# ✅ Check if not none
when: my_var is not none

# ✅ Check truthiness with default
when: my_var | default(false) | bool

is sameas Test (Strict Identity Check)

If you truly need to distinguish True from truthy:

# Strict boolean identity check (rare)
when: my_var is sameas true
when: my_var is sameas false

This passes lint and tests identity, not equality. Use only when you need to distinguish True from 1 or "yes".

Suppressing the Rule

If you have a legitimate reason:

# Per-task skip
- name: Strict check needed
  ansible.builtin.debug:
    msg: "Exact boolean required"
  when: flag == True  # noqa: literal-compare

# Per-file in .ansible-lint
skip_list:
  - literal-compare

Quick Reference

Instead ofWrite
when: x == Truewhen: x
when: x == Falsewhen: not x
when: x != Truewhen: not x
when: x != Falsewhen: x
when: x == True and y == Truewhen: x and y
String variablewhen: x | bool

Conclusion

Replace when: x == True with when: x and when: x == False with when: not x. Use | bool when variables might be strings from inventory or extra-vars. The rule improves readability, prevents string/boolean comparison bugs, and keeps conditions consistent across your playbooks.