elastic/elasticsearch · error · ClassCastException
Cannot apply [<] operation to type [boolean]
Error message
Cannot apply [<] operation to type [boolean]
What it means
Thrown by DefMath.lt(boolean, boolean) which unconditionally throws. The Painless compiler's promote() method maps a (boolean, boolean) pair to boolean.class, so the less-than operator dispatches to this overload at compile time. Unlike Java which rejects this at compile time, Painless defers it to a runtime ClassCastException because the method table must include a boolean slot for every operator.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:608
private static boolean lt(int a, int b) {
return a < b;
}
private static boolean lt(long a, long b) {
return a < b;
}
private static boolean lt(float a, float b) {
return a < b;
}
private static boolean lt(double a, double b) {
return a < b;
}
private static boolean lt(boolean a, boolean b) {
throw new ClassCastException("Cannot apply [<] operation to type [boolean]");
}
private static boolean lt(Object left, Object right) {
if (left instanceof Number) {
if (right instanceof Number) {
if (left instanceof Double || right instanceof Double) {
return ((Number) left).doubleValue() < ((Number) right).doubleValue();
} else if (left instanceof Float || right instanceof Float) {
return ((Number) left).floatValue() < ((Number) right).floatValue();
} else if (left instanceof Long || right instanceof Long) {
return ((Number) left).longValue() < ((Number) right).longValue();
} else {
return ((Number) left).intValue() < ((Number) right).intValue();
}
} else if (right instanceof Character) {
if (left instanceof Double) {
return ((Number) left).doubleValue() < (char) right;
} else if (left instanceof Long) {View on GitHub (pinned to db6a809a66)
Solutions
- Replace the relational comparison with a logical operator: use == , != , or conditional logic instead of <
- Convert booleans to integers before comparing: int ia = a ? 1 : 0; int ib = b ? 1 : 0; then compare ia < ib
- Re-examine the field mapping — if ordering is needed, the field should be numeric, not boolean
Example fix
// before boolean isActive = doc['active'].value; boolean isVerified = doc['verified'].value; boolean result = isActive < isVerified; // after int activeFlag = doc['active'].value ? 1 : 0; int verifiedFlag = doc['verified'].value ? 1 : 0; boolean result = activeFlag < verifiedFlag;
Defensive patterns
Strategy: type-guard
Validate before calling
// Before comparing booleans, convert to integers if ordering is needed boolean a = doc['flag1'].value; boolean b = doc['flag2'].value; int ia = a ? 1 : 0; int ib = b ? 1 : 0; // Now safe to use relational operators return ia < ib;
Type guard
// Check if a type supports relational comparison
boolean isRelationalComparable(Class<?> clazz) {
return clazz == int.class || clazz == long.class ||
clazz == float.class || clazz == double.class ||
clazz == char.class;
} Prevention
- Never apply <, <=, >, >= to boolean fields — use == or != instead
- If boolean ordering is needed, convert to 0/1 integers explicitly
- Review script logic when refactoring from numeric to boolean fields
- Use the Painless compiler's type checking by declaring explicit types instead of def
When it happens
Trigger: A Painless script applies the < operator to two operands that are both statically typed as boolean. The compiler resolves both to boolean.class, binary promotion yields boolean.class, and the lt(boolean, boolean) overload is selected.
Common situations: Comparing two boolean fields or flags with < instead of a logical operator; attempting to sort or rank by a boolean field; copy-pasting comparison logic from numeric code into a boolean context; runtime field mapped as boolean used in a relational comparison.
Related errors
- Cannot apply [<] operation to types [{}] and [{}].
- Cannot apply [<=] operation to type [boolean]
- Cannot apply [>] operation to type [boolean]
- Cannot apply [>=] operation to type [boolean]
- Cannot apply [<=] operation to types [{}] and [{}].
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/c5e9760080fb0440.
Report an issue: GitHub.