elastic/elasticsearch · error · ClassCastException

Cannot apply [~] operation to type [{}].

Error message

Cannot apply [~] operation to type [{}].

What it means

DefMath.not(Object) is the catch-all overload for bitwise NOT on def values whose runtime type is a boxed Number but not one of the supported integral wrappers (Long, Integer, Short, Character, Byte). After all instanceof checks fail, the method throws a ClassCastException naming the actual type.

Source

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

    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() + "].");
    }

    // unary negation and plus: applicable to all numeric types

    private static int neg(int v) {
        return -v;
    }

    private static long neg(long v) {
        return -v;
    }

    private static float neg(float v) {
        return -v;
    }

    private static double neg(double v) {
        return -v;

View on GitHub (pinned to db6a809a66)

Solutions

  1. Convert the value to a supported integral type before applying ~: `def y = ~(long) x;`
  2. Check with instanceof and branch: only apply ~ to Long, Integer, Short, Character, or Byte.
  3. Avoid def; declare the variable as int or long so the type is known at compile time.

Example fix

// before
def x = doc['big_value'].value;
def y = ~x;

// after
def x = doc['big_value'].value;
def y = ~(long) x;
Defensive patterns

Strategy: type-guard

Validate before calling

// Painless: convert unsupported numeric types to long before ~
def x = doc['value'].value;
if (x instanceof Number) {
    def y = ~(long) x;
}

Type guard

// Painless type guard for supported integral types
def isSupportedIntegral(def value) {
    return value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Character || value instanceof Byte;
}

Prevention

When it happens

Trigger: A Painless script applies ~ to a def variable whose runtime type is an unsupported numeric type such as BigInteger, BigDecimal, or AtomicLong. Example: `def x = new BigInteger('255'); def y = ~x;`

Common situations: Interfacing with Java libraries from a Painless script that return BigInteger or BigDecimal. Processing values from third-party ingest plugins that store non-standard numeric types in document fields.

Related errors


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