elastic/elasticsearch · error · ClassCastException
Cannot apply operator [{}] to type [{}]
Error message
Cannot apply operator [{}] to type [{}] What it means
DefMath.lookupUnary throws this ClassCastException at compile/link time when no method handle is registered in TYPE_OP_MAPPING for the (promoted, unboxed) receiver type of a unary or shift operator. The mapping table only contains entries for boolean, int, long, float, double, and Object. If the receiver class promotes/unboxes to something with no entry for the requested operator name (e.g. a shift on a promoted float that has no valid handle, or an unknown operator name), the lookup returns null and this error fires.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:1159
map.put("lt", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "lt", comparison));
map.put("lte", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "lte", comparison));
map.put("gt", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "gt", comparison));
map.put("gte", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "gte", comparison));
map.put("lsh", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "lsh", shift));
map.put("rsh", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "rsh", shift));
map.put("ush", PRIVATE_METHOD_HANDLES_LOOKUP.findStatic(clazz, "ush", shift));
return map;
} catch (ReflectiveOperationException e) {
throw new AssertionError(e);
}
}))
);
/** Returns an appropriate method handle for a unary or shift operator, based only on the receiver (LHS) */
public static MethodHandle lookupUnary(Class<?> receiverClass, String name) {
MethodHandle handle = TYPE_OP_MAPPING.get(promote(unbox(receiverClass))).get(name);
if (handle == null) {
throw new ClassCastException("Cannot apply operator [" + name + "] to type [" + receiverClass + "]");
}
return handle;
}
/** Returns an appropriate method handle for a binary operator, based on promotion of the LHS and RHS arguments */
public static MethodHandle lookupBinary(Class<?> classA, Class<?> classB, String name) {
MethodHandle handle = TYPE_OP_MAPPING.get(promote(promote(unbox(classA)), promote(unbox(classB)))).get(name);
if (handle == null) {
throw new ClassCastException("Cannot apply operator [" + name + "] to types [" + classA + "] and [" + classB + "]");
}
return handle;
}
/** Returns a generic method handle for any operator, that can handle all valid signatures, nulls, corner cases */
public static MethodHandle lookupGeneric(String name) {
return TYPE_OP_MAPPING.get(Object.class).get(name);
}
View on GitHub (pinned to db6a809a66)
Solutions
- Check the receiver type in the script; for shift/bitwise ops it must be int or long. Cast or redeclare accordingly.
- Verify the operator is valid for the type (e.g. '!' is for boolean, '~' is for integers).
- If this fires unexpectedly on valid code, suspect a Painless compiler regression and check the operator name spelling in the compiler against TYPE_OP_MAPPING keys (not, neg, plus, lsh, rsh, ush, etc.).
Example fix
// before float x = 1.5f; int y = x >> 2; // no handle for float shift // after int x = 1; int y = x >> 2;
Defensive patterns
Strategy: validation
Validate before calling
// Before writing a unary/shift op, confirm the operand type is int or long: // int x = 5; // valid for ~x, -x, x << 1 // float x = 1.5f; // INVALID for any shift or bitwise unary
Prevention
- Restrict bitwise/unary operators to int and long typed variables.
- Let the compiler catch type errors by using explicit types instead of def.
- Consult the Painless operator table to know which operators apply to which types.
When it happens
Trigger: Compiling a Painless script where a unary or shift operator is applied to a statically-typed receiver for which the operator has no registered handle. For example, applying a bitwise NOT or shift to a float/double typed variable (not def) — the compiler resolves the operator via lookupUnary and finds null because only the throwing stubs are registered under those types and the stub is not what the typed path selects.
Common situations: Scripts that attempt unary bitwise/shift operations on floating-point typed variables. Custom operator names or internal compiler bugs that pass an unregistered operator string. Edge cases during language version upgrades where operator registration changed.
Related errors
- Cannot apply operator [{}] to types [{}] and [{}]
- Cannot cast {} to {}
- Cannot apply [-] operation to types [{}] and [{}].
- Cannot apply [<] operation to type [boolean]
- Cannot apply [<] operation to types [{}] and [{}].
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/e02e47d28e4c7a16.
Report an issue: GitHub.