elastic/elasticsearch · error · ClassCastException

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

Error message

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

What it means

Thrown by DefMath.lsh(float, long) which unconditionally throws. When the left operand is statically typed float, the compiler's promote() method yields float.class for the left side, selecting the lsh(float, long) overload. Left-shift is only defined for integral types; the float overload exists for method-table completeness but always fails.

Source

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

            return longIntegralValue(left) | longIntegralValue(right);
        } else {
            return intIntegralValue(left) | intIntegralValue(right);
        }
    }

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

View on GitHub (pinned to db6a809a66)

Solutions

  1. Cast the float left operand to int or long before shifting: int iv = (int) v; int result = iv << shift;
  2. Change the field mapping to an integer type if bit-shifting is the intended use case
  3. Use multiplication (v * Math.pow(2, shift)) if the goal is scaling rather than bit manipulation

Example fix

// before
float val = doc['code'].value;
float shifted = val << 2;

// after
int val = (int) doc['code'].value;
int shifted = val << 2;
Defensive patterns

Strategy: type-guard

Validate before calling

// Before left-shift on float, cast to int
float val = doc['code'].value;
int iv = (int) val;
return iv << 2;

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

When it happens

Trigger: A Painless script applies the << operator where the left operand is statically typed as float. The shift amount (right operand) is promoted to long. The compiler selects lsh(float, long) which unconditionally throws.

Common situations: Bit-shift on a float-typed field; float variable used in a shift expression for packing/encoding logic; refactoring integer shift code to operate on float fields; float-mapped runtime field used in bit-manipulation logic.

Related errors


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