elastic/elasticsearch · error · ClassCastException

Cannot apply not [~] to type [boolean]

Error message

Cannot apply not [~] to type [boolean]

What it means

The bitwise NOT operator (~) operates on individual bits and has no meaning for boolean values. DefMath's boolean overload for not() throws a ClassCastException when a def variable resolves to Boolean at runtime and ~ is applied.

Source

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

    private static int not(int v) {
        return ~v;
    }

    private static long not(long v) {
        return ~v;
    }

    private static float not(float v) {
        throw new ClassCastException("Cannot apply not [~] to type [float]");
    }

    private static double not(double v) {
        throw new ClassCastException("Cannot apply not [~] to type [double]");
    }

    private static boolean not(boolean v) {
        throw new ClassCastException("Cannot apply not [~] to type [boolean]");
    }

    private static Object not(Object unary) {
        if (unary instanceof Long) {
            return ~(Long) unary;
        } else if (unary instanceof Integer) {
            return ~(Integer) unary;
        } else if (unary instanceof Short) {
            return ~(Short) unary;
        } else if (unary instanceof Character) {
            return ~(Character) unary;
        } else if (unary instanceof Byte) {
            return ~(Byte) unary;
        }

        throw new ClassCastException("Cannot apply [~] operation to type " + "[" + unary.getClass().getCanonicalName() + "].");
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use the logical NOT operator (!) instead of bitwise NOT (~) for boolean values.
  2. If an integer representation is needed, cast to int first: `def y = ~(int) x;`
  3. Use an explicit boolean type declaration so the compiler rejects ~ at compile time.

Example fix

// before
def flag = doc['active'].value;
def inverted = ~flag;

// after
boolean flag = doc['active'].value;
boolean inverted = !flag;
Defensive patterns

Strategy: type-guard

Validate before calling

// Painless: use logical NOT (!) for boolean, not bitwise NOT (~)
def x = doc['flag'].value;
if (x instanceof Boolean) {
    boolean inverted = !x;
} else if (x instanceof Integer || x instanceof Long) {
    def y = ~x;
}

Type guard

// Painless type guard distinguishing boolean from integral
def isIntegral(def value) {
    return value instanceof Integer || value instanceof Long || value instanceof Short || value instanceof Byte || value instanceof Character;
}

Prevention

When it happens

Trigger: A Painless script applies ~ to a def variable whose runtime value is a Boolean. Example: `def x = true; def y = ~x;`

Common situations: A script receives a boolean field value from a document (e.g., a flag) and mistakenly applies a bitwise operator instead of a logical operator (!).

Related errors


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