elastic/elasticsearch · error · ClassCastException

Cannot apply [>>] operation to type [double]

Error message

Cannot apply [>>] operation to type [double]

What it means

Painless throws this ClassCastException at runtime when a right-shift (>>) operator is applied to a value that resolves to a double. As with the float stub, DefMath.rsh(double, long) exists only so the dynamic (def) dispatch path produces a readable error; double is an IEEE-754 floating-point type and bitwise shift is undefined for it. Only int and long overloads of rsh actually perform the operation.

Source

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

        } else {
            return intIntegralValue(left) << right;
        }
    }

    private static int rsh(int a, long b) {
        return a >> b;
    }

    private static long rsh(long a, long b) {
        return a >> b;
    }

    private static float rsh(float a, long b) {
        throw new ClassCastException("Cannot apply [>>] operation to type [float]");
    }

    private static double rsh(double a, long b) {
        throw new ClassCastException("Cannot apply [>>] operation to type [double]");
    }

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

    public static Object rsh(Object left, long right) {
        if (left instanceof Long) {
            return (long) left >> right;
        } else {
            return intIntegralValue(left) >> right;
        }
    }

    private static int ush(int a, long b) {
        return a >>> b;
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Cast the operand to int or long before the shift: '(long) x >> 1'.
  2. Declare the variable with an explicit integral type instead of def to force compile-time rejection.
  3. Re-examine the logic: if the value is genuinely continuous, a bitwise shift is likely a bug; replace with multiplication/division by a power of two.

Example fix

// before
def x = doc['score'].value;  // double field
def y = x >> 3;
// after
long x = (long) doc['score'].value;
long y = x >> 3;
Defensive patterns

Strategy: type-guard

Validate before calling

// Cast before shifting to guarantee integral dispatch:
// def x = doc['score'].value;
// long shifted = ((long) x) >> 1;

Type guard

// boolean isIntegral = x instanceof Integer || x instanceof Long || x instanceof Short || x instanceof Byte;

Prevention

When it happens

Trigger: A Painless script uses def and the operand is a double at runtime: 'def x = 3.14; def y = x >> 1;'. This routes through rsh(Object, long) which, after numeric promotion, hits the double stub. Commonly seen when doc field values default to double or when arithmetic produces a double result that is then shifted.

Common situations: Doc fields mapped as double, double_valued expressions, or computed values from division that widen to double. Scripts ported from languages that silently truncate floats before shifting. Runtime-mapped fields that return double.

Related errors


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