elastic/elasticsearch · error · ClassCastException
Cannot apply [<<] operation to type [double]
Error message
Cannot apply [<<] operation to type [double]
What it means
Thrown by DefMath.lsh(double, long) which unconditionally throws. When the left operand is statically typed double, the compiler's promote() method yields double.class for the left side, selecting the lsh(double, long) overload. Left-shift is only defined for integral types; the double overload always fails.
Source
Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/DefMath.java:1000
}
// shift operators, valid for any integral types, but does not promote.
// we implement all shifts as long shifts, because the extra bits are ignored anyway.
private static int lsh(int a, long b) {
return a << b;
}
private static long lsh(long a, long b) {
return a << b;
}
private static float lsh(float a, long b) {
throw new ClassCastException("Cannot apply [<<] operation to type [float]");
}
private static double lsh(double a, long b) {
throw new ClassCastException("Cannot apply [<<] operation to type [double]");
}
private static boolean lsh(boolean a, long b) {
throw new ClassCastException("Cannot apply [<<] operation to type [boolean]");
}
public static Object lsh(Object left, long right) {
if (left instanceof Long) {
return (long) (left) << right;
} else {
return intIntegralValue(left) << right;
}
}
private static int rsh(int a, long b) {
return a >> b;
}
View on GitHub (pinned to db6a809a66)
Solutions
- Cast the double left operand to long before shifting: long lv = (long) v; long result = lv << shift;
- Change the field mapping to a long integer type if bit-shifting is the intended use case
- Use multiplication (v * Math.pow(2, shift)) if the goal is scaling rather than bit manipulation
Example fix
// before double val = doc['encoded'].value; double shifted = val << 4; // after long val = (long) doc['encoded'].value; long shifted = val << 4;
Defensive patterns
Strategy: type-guard
Validate before calling
// Before left-shift on double, cast to long double val = doc['encoded'].value; long lv = (long) val; return lv << 4;
Type guard
// Check that the left operand is integral before shift
boolean isShiftable(Object v) {
return v instanceof Integer || v instanceof Long ||
v instanceof Short || v instanceof Byte;
} Prevention
- Never apply << to double-typed variables — cast to long first
- Change field mapping from double/scaled_float to long if bit-shifting is needed
- Consider multiplication (v * Math.pow(2, n)) if scaling rather than bit manipulation is the goal
- Audit scripts that use << on fields mapped as double or scaled_float
When it happens
Trigger: A Painless script applies the << operator where the left operand is statically typed as double. The shift amount (right operand) is promoted to long. The compiler selects lsh(double, long) which unconditionally throws.
Common situations: Bit-shift on a double-typed field or scaled_float mapping; double variable used in shift encoding/packing logic; refactoring integer shift code to operate on double fields; double-typed runtime field in bit-manipulation logic.
Related errors
- Cannot apply [<<] operation to type [float]
- Cannot apply [<<] operation to type [boolean]
- 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/78b30f2915f406b3.
Report an issue: GitHub.