{"record":{"id":"cf3c536c3975618f","repo":"kestra-io/kestra","slug":"could-not-perform-less-than-comparisonpebb","errorCode":null,"errorMessage":"Could not perform less than comparisonPebb","messagePattern":"Could not perform less than comparisonPebb","errorType":"exception","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/expression/LessThanExpression.java","lineNumber":24,"sourceCode":"import io.pebbletemplates.pebble.template.PebbleTemplateImpl;\nimport io.pebbletemplates.pebble.utils.OperatorUtils;\n\npublic class LessThanExpression extends BinaryExpression<Boolean> {\n    @Override\n    public Boolean evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) {\n        Object left = this.getLeftExpression().evaluate(self, context);\n        Object right = this.getRightExpression().evaluate(self, context);\n\n        // add support for string comparison\n        if (left instanceof String sLeft && right instanceof String sRight) {\n            return sLeft.compareTo(sRight) < 0;\n        }\n\n        // default implementation from io.pebbletemplates.pebble.node.expression.LessThanExpression\n        try {\n            return OperatorUtils.lt(left, right);\n        } catch (Exception ex) {\n            throw new PebbleException(\n                ex, \"Could not perform less than comparisonPebb\", this.getLineNumber(), self\n                    .getName()\n            );\n        }\n    }\n}\n","sourceCodeStart":6,"sourceCodeEnd":31,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/expression/LessThanExpression.java#L6-L31","documentation":"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.","triggerScenarios":"Using '<' between non-comparable types: '{{ mymap < 1 }}', '{{ null < 5 }}', '{{ somelist < 10 }}'. One operand being null and the other non-string is the typical cause.","commonSituations":"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.","solutions":["Ensure both sides of '<' are strings or numbers.","Default the operand to a safe value: '{{ (outputs.task.value ?? 0) < limit }}'.","Search logs for 'comparisonPebb' (the typo) as well as 'comparison' when troubleshooting."],"exampleFix":"{# before #}\n{% if outputs.task.value < threshold %}\n\n{# after #}\n{% if (outputs.task.value ?? 0) < (threshold ?? 0) %}","handlingStrategy":"validation","validationCode":"{# Default both sides to a numeric value before using < #}\n{% set left = (vars.value ?? 0) %}\n{% set right = (vars.threshold ?? 0) %}\n{% if left < right %}...{% endif %}","typeGuard":"{# Ensure operand is scalar before comparing #}\n{% set safe_val = outputs.task.value ?? 0 %}\n{% if safe_val is not null and safe_val is not iterable %}\n  {{ safe_val < limit }}\n{% endif %}","tryCatchPattern":null,"preventionTips":["Use ?? defaults on both operands to prevent null-vs-number type errors.","Be aware the error message contains a typo ('comparisonPebb') — search for both spellings when grepping logs.","Validate task output types before using them in comparison expressions."],"tags":["pebble","comparison","less-than","type-mismatch","typo"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}