elastic/elasticsearch · error · ClassCastException

Cannot apply [<=] operation to types [{}] and [{}].

Error message

Cannot apply [<=] operation to types [{}] and [{}].

What it means

Thrown by DefMath.lte(Object, Object) when the runtime types of both operands do not match any supported less-than-or-equal combination. The Object overload dispatches through instanceof Number and instanceof Character checks; unrecognized type pairs fall through to this ClassCastException. Only triggered with def-typed operands.

Source

Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:719

                }
            }
        } 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 gt(int a, int b) {
        return a > b;
    }

    private static boolean gt(long a, long b) {
        return a > b;
    }

    private static boolean gt(float a, float b) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use explicit numeric types for both operands to get compile-time type checking
  2. Add an instanceof Number guard: if (a instanceof Number && b instanceof Number) { return ((Number)a).doubleValue() <= ((Number)b).doubleValue(); }
  3. Fix the mapping to use a consistent numeric type for the field
  4. If comparing date strings, parse to long epoch millis first using Long.parseLong() or a date formatter

Example fix

// before
def val = doc['price'].value;
def cap = params['max'];
boolean ok = val <= cap;

// after
double val = doc['price'].value;
double cap = (double) params['max'];
boolean ok = val <= cap;
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard def comparison with type checks
def val = doc['score'].value;
def limit = params['cap'];
if (val instanceof Number && limit instanceof Number) {
  return ((Number) val).doubleValue() <= ((Number) limit).doubleValue();
}
return false;

Type guard

// Check numeric compatibility before <= comparison
boolean bothNumeric(def a, def b) {
  return a instanceof Number && b instanceof Number;
}

Prevention

When it happens

Trigger: A Painless script applies <= to two def-typed values where at least one resolves at runtime to a non-numeric, non-character type (String, List, Map, null). The Object overload is invoked and no instanceof branch matches.

Common situations: Field mapped as keyword/text used in a <= threshold check; def variable from an untyped source (params map, _source parsing) compared numerically; heterogeneous documents where field type varies; comparing a date-formatted string against a numeric epoch.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/37f57f40f9f72fbb. Report an issue: GitHub.