elastic/elasticsearch · error · ClassCastException

Cannot apply [>=] operation to type [boolean]

Error message

Cannot apply [>=] operation to type [boolean]

What it means

Thrown by DefMath.gte(boolean, boolean) which unconditionally throws. When both operands are statically typed boolean, binary promotion yields boolean.class and the compiler selects this overload. Greater-than-or-equal is undefined for booleans in Painless's operator table.

Source

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

    private static boolean gte(int a, int b) {
        return a >= b;
    }

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

    private static boolean gte(float a, float b) {
        return a >= b;
    }

    private static boolean gte(double a, double b) {
        return a >= b;
    }

    private static boolean gte(boolean a, boolean b) {
        throw new ClassCastException("Cannot apply [>=] operation to type [boolean]");
    }

    private static boolean gte(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

  1. Use == or != for boolean comparisons instead of >=
  2. Convert booleans to integers if ordering semantics are needed
  3. Re-examine the data model: if ordering matters, use an integer or enum-like numeric field

Example fix

// before
boolean vip = doc['is_vip'].value;
boolean elite = doc['is_elite'].value;
boolean atLeast = vip >= elite;

// after
int vipLevel = doc['is_vip'].value ? 1 : 0;
int eliteLevel = doc['is_elite'].value ? 1 : 0;
boolean atLeast = vipLevel >= eliteLevel;
Defensive patterns

Strategy: type-guard

Validate before calling

// Convert booleans to integers before using >=
boolean a = doc['is_valid'].value;
boolean b = doc['is_checked'].value;
int ia = a ? 1 : 0;
int ib = b ? 1 : 0;
return ia >= ib;

Type guard

// Reject boolean before relational comparison
boolean isComparable(Object v) {
  return v instanceof Number || v instanceof Character;
}

Prevention

When it happens

Trigger: A Painless script applies the >= operator to two operands both statically typed as boolean. The promote() method maps (boolean, boolean) to boolean.class, dispatching to gte(boolean, boolean).

Common situations: Using >= on boolean flags in a script_score or runtime field; attempting to establish a boolean ordering or hierarchy; refactored code that previously used numeric fields but was changed to boolean; filter or condition logic mistakenly using >= instead of == on boolean fields.

Related errors


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