elastic/elasticsearch · error · ClassCastException
Cannot apply [%] operation to types [{}] and [{}].
Error message
Cannot apply [%] operation to types [{}] and [{}]. What it means
DefMath.rem(Object, Object) handles the remainder operator on def values for Number and Character combinations. If neither operand matches any supported branch, the method throws a ClassCastException naming both operands' actual runtime types.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:352
}
}
} 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()
+ "]."
);
}
// addition: applicable to all numeric types.
// additionally, if either type is a string, the other type can be any arbitrary type (including null)
private static int add(int a, int b) {
return a + b;
}
private static long add(long a, long b) {
return a + b;View on GitHub (pinned to db6a809a66)
Solutions
- Cast both operands to compatible numeric types: `def z = (int) x % (int) y;`
- Guard with instanceof to verify both are Number or Character.
- Use explicit types instead of def for arithmetic variables.
Example fix
// before
def n = doc['count'].value;
def m = doc['bucket'].value;
def r = n % m;
// after
def n = doc['count'].value;
def m = doc['bucket'].value;
if (n instanceof Number && m instanceof Number) {
def r = (int) n % (int) m;
} Defensive patterns
Strategy: type-guard
Validate before calling
// Painless: verify both operands are Number or Character before modulo
def a = doc['val1'].value;
def b = doc['val2'].value;
if (a instanceof Number && b instanceof Number) {
def result = (int) a % (int) b;
} Type guard
// Painless type guard for modulo-compatible types
def canMod(def a, def b) {
return (a instanceof Number && b instanceof Number) || (a instanceof Number && b instanceof Character) || (a instanceof Character && b instanceof Number) || (a instanceof Character && b instanceof Character);
} Prevention
- Cast def values to int or long before applying the % operator.
- Use explicit types instead of def for modulo operands.
- Check instanceof on both operands to avoid incompatible-type falls-through.
When it happens
Trigger: A Painless script applies % to two def variables whose runtime types are incompatible with the remainder operation. Example: `def x = 'hello'; def y = 3; def z = x % y;` where x is a String.
Common situations: Applying modulo to a def value that resolved to a String from a text or keyword field. Processing fields with heterogeneous types across documents.
Related errors
- Cannot apply [%] operation to type [boolean]
- Cannot apply not [~] to type [float]
- Cannot apply not [~] to type [double]
- Cannot apply [~] operation to type [{}].
- Cannot apply [-] operation to type [boolean]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/33214bcfaa6aa34f.
Report an issue: GitHub.