kestra-io/kestra · error · PebbleException
Could not perform less than or equals comparison
Error message
Could not perform less than or equals comparison
What it means
Thrown by the custom LessThanEqualsExpression Pebble node when the '<=' comparison cannot be evaluated. The expression tries string comparison first, then OperatorUtils.lte for numbers; if lte throws due to incomparable operand types, the exception is wrapped with this message.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/expression/LessThanEqualsExpression.java:24
import io.pebbletemplates.pebble.template.PebbleTemplateImpl;
import io.pebbletemplates.pebble.utils.OperatorUtils;
public class LessThanEqualsExpression 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.lte(left, right);
} catch (Exception ex) {
throw new PebbleException(
ex, "Could not perform less than or equals comparison", this.getLineNumber(), self
.getName()
);
}
}
}
View on GitHub (pinned to 823fada927)
Solutions
- Confirm both operands are strings or numbers before comparison.
- Default the variable to a numeric value: '{{ (vars.metric ?? 0) <= 100 }}'.
- Add explicit type validation in the upstream task to guarantee the output type.
Example fix
{# before #}
{% if outputs.task.count <= max_items %}
{# after #}
{% if (outputs.task.count ?? 0) <= (max_items ?? 100) %} Defensive patterns
Strategy: validation
Validate before calling
{# Default both sides to a numeric value before using <= #}
{% set left = (vars.metric ?? 0) %}
{% set right = (vars.ceiling ?? 100) %}
{% if left <= right %}...{% endif %} Type guard
{# Ensure operand is not null or complex before comparing #}
{% set safe_val = outputs.task.count ?? 0 %}
{% if safe_val is not null and safe_val is not iterable %}
{{ safe_val <= max_items }}
{% endif %} Prevention
- Always provide a numeric fallback with ?? for comparison operands.
- Confirm upstream task outputs are typed as integers or numbers.
- Test comparison conditions with null and edge-case values.
When it happens
Trigger: Using '<=' with mismatched or non-comparable operand types: '{{ mylist <= 10 }}', '{{ null <= 5 }}', '{{ somemap <= "x" }}'. One side being null while the other is non-string is the most common trigger.
Common situations: Flow conditions comparing outputs that may be null or complex. Threshold checks where the monitored value comes from an upstream task that could produce an unexpected type. Template logic written assuming a numeric output that occasionally resolves to an object.
Related errors
- Could not perform greater than or equals comparison
- Could not perform greater than comparison
- Could not perform less than comparisonPebb
- Cannot concat {} with {}
- 'chunk' filter can only be applied to List. Actual type was:
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/0cf2eb4fd563fe06.
Report an issue: GitHub.