elastic/elasticsearch · error · ClassCastException

Cannot apply [>] operation to types [{}] and [{}].

Error message

Cannot apply [>] operation to types [{}] and [{}].

What it means

Thrown by DefMath.gt(Object, Object) when the runtime types of both operands do not match any supported greater-than combination. The Object overload checks instanceof Number and instanceof Character; type pairs outside those categories 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:788

                }
            }
        } 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 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) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use explicit numeric types for both operands
  2. Guard with instanceof: if (a instanceof Number && b instanceof Number) { return ((Number)a).doubleValue() > ((Number)b).doubleValue(); }
  3. Fix the mapping or use a multi-field with a numeric sub-field
  4. Check for null/missing fields before comparison: if (doc['field'].size() == 0) return false;

Example fix

// before
def score = doc['rating'].value;
def cutoff = params['threshold'];
boolean pass = score > cutoff;

// after
double score = doc['rating'].value;
double cutoff = (double) params['threshold'];
boolean pass = score > cutoff;
Defensive patterns

Strategy: type-guard

Validate before calling

// Type-check def values before > comparison
def val = doc['rating'].value;
def threshold = params['min'];
if (val instanceof Number && threshold instanceof Number) {
  return ((Number) val).doubleValue() > ((Number) threshold).doubleValue();
}
return false;

Type guard

// Guard for def > comparison
boolean safeGreaterThan(def a, def b) {
  if (a instanceof Number && b instanceof Number) {
    return ((Number) a).doubleValue() > ((Number) b).doubleValue();
  }
  return false;
}

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. The Object overload is invoked via def dispatch and no instanceof branch matches.

Common situations: Keyword/text field compared with > against a numeric threshold in a script; def variable holding a parsed JSON value of unexpected type; field that is null or missing, returning a non-numeric default; cross-index search where the field has different mappings.

Related errors


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