ansible/ansible · error · AnsibleBrokenConditionalError

Conditional result ({bool_result}) was derived from value of

Error message

Conditional result ({bool_result}) was derived from value of type {native_type_name(result)!r} at {str(result_origin)!r}. Conditionals must have a boolean result.

What it means

AnsibleBrokenConditionalError raised by evaluate_conditional() when the conditional's evaluated result is not a bool. The message reports the coerced truthiness (bool_result), the native type of the result, and the origin-tagged location of the result value, then rejects non-boolean conditionals. With allow_broken_conditionals the truthy value is accepted with a deprecation warning instead.

Source

Thrown at lib/ansible/_internal/_templating/_engine.py:591

        result_origin = Origin.get_tag(result) or Origin.UNKNOWN

        msg = (
            f'Conditional result ({bool_result}) was derived from value of type {native_type_name(result)!r} at {str(result_origin)!r}. '
            'Conditionals must have a boolean result.'
        )

        if _TemplateConfig.allow_broken_conditionals:
            _display.deprecated(
                msg=msg,
                obj=conditional,
                help_text=self._BROKEN_CONDITIONAL_ALLOWED_FRAGMENT,
                version='2.23',
            )

            return bool_result

        raise AnsibleBrokenConditionalError(msg, obj=conditional)

    @staticmethod
    def _trust_check(value: str, skip_handler: bool = False) -> bool:
        """
        Return True if the given value is trusted for templating, otherwise return False.
        When the value is not trusted, a warning or error may be generated, depending on configuration.
        """
        if TrustedAsTemplate.is_tagged_on(value):
            return True

        if not skip_handler:
            with Skippable, _TemplateConfig.untrusted_template_handler.handle(TemplateTrustCheckFailedError, skip_on_ignore=True):
                raise TemplateTrustCheckFailedError(obj=value)

        return False

View on GitHub (pinned to 9cf16a4aca)

Solutions

  1. Make the comparison explicit: `when: "{{ result.stdout | length > 0 }}"` or add `| bool`.
  2. Define the source variable as a real boolean in YAML (true/false), not a quoted string.
  3. For list checks use `| length > 0`; for strings use explicit comparisons or `| bool`.
  4. Temporarily enable allow_broken_conditionals to locate all offenders via deprecation warnings, then fix each before 2.23.

Example fix

# before
when: "{{ result.stdout }}"

# after
when: "{{ result.stdout | trim | length > 0 }}"
Defensive patterns

Strategy: type-guard

Validate before calling

# preflight in playbook: assert the conditional input is boolean-shaped
- assert:
    that: flag | type_debug in ['bool', 'AnsibleUnicode', 'str']
  when: flag is defined

Type guard

from ansible._internal._errors import _messages  # controller-side helper
def yields_boolean(templar, cond) -> bool:
    """Template the conditional and verify the result type before evaluation."""
    val = templar.template(cond, mode=templar._TemplateMode_DEFAULT) if isinstance(cond, str) else cond
    return isinstance(val, bool)

Try / catch

try:
    ok = templar.evaluate_conditional(cond)
except AnsibleBrokenConditionalError as ex:
    if 'Conditionals must have a boolean result' in str(ex):
        ok = templar.evaluate_conditional('{{ (%s) | bool }}' % cond)
    else:
        raise

Prevention

When it happens

Trigger: A `when:` expression that evaluates to a string/number/list instead of a bool, e.g. `when: "{{ result.stdout }}"` (string), `when: "{{ items }}"` (list), or `when: count` where count is an int. Any truthy non-bool result after templating triggers it.

Common situations: Migrating from older ansible-core that accepted truthy strings ('yes', 'on', any non-empty string) as True; conditionals returning module output directly; using `| default(...)` with string defaults; vars defined as 'no'/'yes' strings that no longer coerce.

Related errors


AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15). Data as JSON: /api/errors/3bc95d27cd542a15. Report an issue: GitHub.