elastic/elasticsearch · error · ClassCastException

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

Error message

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

What it means

Painless throws this ClassCastException at runtime when a right-shift (>>) operator is applied to a value that resolves to a float. DefMath registers overloaded rsh() stubs for every type the compiler must account for (int, long, float, double, boolean), but only int and long actually compute a shift; the float/double/boolean overloads exist solely to surface a clear error for the dynamic (def) code path where the compiler cannot know the type at compile time. Shifts are bitwise operations and have no meaning on IEEE-754 floating point, so the runtime refuses them.

Source

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

    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;
    }

    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;
        }
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Change the shift operand to an integral type before shifting: cast with '(int) x >> 2' or '(long) x >> 2'.
  2. Stop using def for the variable; declare it as int or long so the compiler catches the type mismatch at compile time instead of the user at runtime.
  3. If the source field is genuinely floating-point, replace the shift with an equivalent arithmetic operation (e.g. divide by a power of two) since bitwise shift has no defined meaning on floats.

Example fix

// before
def x = doc['weight'].value;  // weight is a float field
def y = x >> 2;
// after
int x = (int) doc['weight'].value;
int y = x >> 2;
Defensive patterns

Strategy: type-guard

Validate before calling

// In Painless, before shifting a def value, narrow it:
// def x = ...;
// if (x instanceof Integer || x instanceof Long) { int y = ((Number)x).intValue() >> 2; }

Type guard

// Painless has no instanceof-over-def for primitives cleanly, but you can check:
// def x = doc['f'].value;
// boolean isIntegral = x instanceof Integer || x instanceof Long || x instanceof Short || x instanceof Byte;

Prevention

When it happens

Trigger: A Painless script declares a variable as def and assigns a float value, then uses >> on it: 'def x = 1.5f; def y = x >> 2;'. At runtime the DefMath.rsh(float, long) stub is invoked through the dynamic dispatch in rsh(Object, long) and throws. Static (typed) float code is rejected at compile time; this specific exception only fires through the def/Object path.

Common situations: Scripts that read dynamically-typed fields from documents (e.g. doc['some_field'].value) where the field is mapped as float/scaled_float, followed by an attempt to do bit manipulation. Migrating a script from an integer field to a floating-point field without updating the shift logic. Aggregations or runtime fields using def and assuming numeric fields are integers.

Related errors


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