elastic/elasticsearch · error · ClassCastException
Cannot apply [<] operation to types [{}] and [{}].
Error message
Cannot apply [<] operation to types [{}] and [{}]. What it means
Thrown by DefMath.lt(Object, Object) when the runtime types of both operands do not match any supported less-than combination. The Object overload checks instanceof Number and instanceof Character; if neither branch matches the actual runtime types, it falls through to this ClassCastException. Only occurs with def-typed operands.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:650
}
}
} else if (left instanceof Character) {
if (right instanceof Number) {
if (right instanceof Double) {
return (char) left < ((Number) right).doubleValue();
} else if (right instanceof Long) {
return (char) left < ((Number) right).longValue();
} else if (right instanceof Float) {
return (char) left < ((Number) right).floatValue();
} else {
return (char) left < ((Number) right).intValue();
}
} else if (right instanceof Character) {
return (char) left < (char) right;
}
}
throw new ClassCastException(
"Cannot apply [<] operation to types "
+ "["
+ left.getClass().getCanonicalName()
+ "] and ["
+ right.getClass().getCanonicalName()
+ "]."
);
}
private static boolean lte(int a, int b) {
return a <= b;
}
private static boolean lte(long a, long b) {
return a <= b;
}
private static boolean lte(float a, float b) {View on GitHub (pinned to db6a809a66)
Solutions
- Declare both operands with explicit types so the compiler catches incompatibility at parse time
- Guard with instanceof before comparing: if (a instanceof Number && b instanceof Number) { return ((Number)a).doubleValue() < ((Number)b).doubleValue(); }
- Ensure the index mapping types the field consistently as numeric across all documents and indices
- If comparing strings, use String.compareTo() or String.compareToIgnoreCase() instead of the < operator
Example fix
// before def threshold = params['min']; def value = doc['score'].value; def passes = value < threshold; // after double value = doc['score'].value; double threshold = (double) params['min']; boolean passes = value < threshold;
Defensive patterns
Strategy: type-guard
Validate before calling
// Before comparing def values, verify types are compatible
def a = doc['field1'].value;
def b = params['threshold'];
if (a instanceof Number && b instanceof Number) {
return ((Number) a).doubleValue() < ((Number) b).doubleValue();
} else if (a instanceof String && b instanceof String) {
return ((String) a).compareTo((String) b) < 0;
} else {
return false;
} Type guard
// Type guard for def relational comparison
boolean canCompareNumerically(def a, def b) {
return a instanceof Number && b instanceof Number;
} Prevention
- Use explicit numeric types instead of def for values involved in comparisons
- Validate field types in the mapping before writing comparison scripts
- Handle the case where a field is missing: check doc['field'].size() > 0 first
- For string comparisons, use String.compareTo() instead of relational operators
When it happens
Trigger: A Painless script applies < to two def-typed values where at least one evaluates at runtime to a non-numeric, non-character type. The compiler emits a call to lt(Object, Object); runtime instanceof dispatch finds no matching branch.
Common situations: Comparing a keyword/string field value against a number in a script; def variable holding a List or Map compared with <; field that changed type after a reindex or mapping conflict; script processing heterogeneous documents where the same field name has different types.
Related errors
- Cannot apply [<] operation to type [boolean]
- Cannot apply [<=] operation to types [{}] and [{}].
- Cannot apply [>] operation to types [{}] and [{}].
- Cannot apply [-] operation to types [{}] and [{}].
- Cannot apply [<=] operation to type [boolean]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/1df489ffa5961b03.
Report an issue: GitHub.