elastic/elasticsearch · error · ClassCastException

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

Error message

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

What it means

Thrown by DefMath.lsh(boolean, long) which unconditionally throws. When the left operand is statically typed boolean, the compiler's promote() method yields boolean.class for the left side, selecting the lsh(boolean, long) overload. Left-shift has no semantics for boolean values; the overload exists for method-table completeness but always raises this exception.

Source

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

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

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

View on GitHub (pinned to db6a809a66)

Solutions

  1. Convert the boolean to an integer before shifting: int iv = b ? 1 : 0; int result = iv << shift;
  2. Change the field mapping to an integer type (0/1) if bit-shifting is the intended use case
  3. Re-examine the logic: shifting a boolean is almost certainly a design error

Example fix

// before
boolean flag = doc['enabled'].value;
int packed = flag << 3;

// after
int flag = doc['enabled'].value ? 1 : 0;
int packed = flag << 3;
Defensive patterns

Strategy: type-guard

Validate before calling

// Before left-shift on boolean, convert to int
boolean flag = doc['enabled'].value;
int iv = flag ? 1 : 0;
return iv << 3;

Type guard

// Check that the left operand is not boolean 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 boolean. The shift amount (right operand) is promoted to long. The compiler selects lsh(boolean, long) which unconditionally throws.

Common situations: Bit-shift on a boolean-typed field; boolean variable mistakenly used in a shift expression; refactoring code that previously used integer flags but was changed to boolean fields; boolean-typed runtime field in encoding/packing logic.

Related errors


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