kestra-io/kestra · error · PebbleException

Could not perform less than comparisonPebb

Error message

Could not perform less than comparisonPebb

What it means

Thrown by the custom LessThanExpression Pebble node when the '<' comparison fails. The expression attempts string comparison then delegates to OperatorUtils.lt; if lt throws because the operand types are incompatible, the error is wrapped. NOTE: the message text contains a typo — it reads 'comparisonPebb' instead of 'comparison', likely a copy-paste artifact from the PebbleException class name leaking into the string literal.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/expression/LessThanExpression.java:24

import io.pebbletemplates.pebble.template.PebbleTemplateImpl;
import io.pebbletemplates.pebble.utils.OperatorUtils;

public class LessThanExpression extends BinaryExpression<Boolean> {
    @Override
    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) {
        Object left = this.getLeftExpression().evaluate(self, context);
        Object right = this.getRightExpression().evaluate(self, context);

        // add support for string comparison
        if (left instanceof String sLeft && right instanceof String sRight) {
            return sLeft.compareTo(sRight) < 0;
        }

        // default implementation from io.pebbletemplates.pebble.node.expression.LessThanExpression
        try {
            return OperatorUtils.lt(left, right);
        } catch (Exception ex) {
            throw new PebbleException(
                ex, "Could not perform less than comparisonPebb", this.getLineNumber(), self
                    .getName()
            );
        }
    }
}

View on GitHub (pinned to 823fada927)

Solutions

  1. Ensure both sides of '<' are strings or numbers.
  2. Default the operand to a safe value: '{{ (outputs.task.value ?? 0) < limit }}'.
  3. Search logs for 'comparisonPebb' (the typo) as well as 'comparison' when troubleshooting.

Example fix

{# before #}
{% if outputs.task.value < threshold %}

{# after #}
{% if (outputs.task.value ?? 0) < (threshold ?? 0) %}
Defensive patterns

Strategy: validation

Validate before calling

{# Default both sides to a numeric value before using < #}
{% set left = (vars.value ?? 0) %}
{% set right = (vars.threshold ?? 0) %}
{% if left < right %}...{% endif %}

Type guard

{# Ensure operand is scalar before comparing #}
{% set safe_val = outputs.task.value ?? 0 %}
{% if safe_val is not null and safe_val is not iterable %}
  {{ safe_val < limit }}
{% endif %}

Prevention

When it happens

Trigger: Using '<' between non-comparable types: '{{ mymap < 1 }}', '{{ null < 5 }}', '{{ somelist < 10 }}'. One operand being null and the other non-string is the typical cause.

Common situations: Size or threshold comparisons in flow conditions where the left operand is a task output of uncertain type. Comparing a variable that sometimes resolves to null. The typo in the message ('comparisonPebb') does not affect behavior but may confuse log searches.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/cf3c536c3975618f. Report an issue: GitHub.