elastic/elasticsearch · error · ClassCastException

Cannot convert [{}] to an integral value.

Error message

Cannot convert [{}] to an integral value.

What it means

Thrown by DefMath.longIntegralValue(Object) when the object is not one of Long, Integer, Short, Byte, or Character. This helper is called by the Object overload of bitwise operators (&, ^, |) when at least one operand is a Long, requiring both operands to be converted to long. Float, Double, Boolean, String, and other types are rejected because bitwise operations are only defined for integral types in Java semantics.

Source

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

                + left.getClass().getCanonicalName()
                + "] and ["
                + right.getClass().getCanonicalName()
                + "]."
        );
    }

    // helper methods to convert an integral according to numeric promotion
    // this is used by the generic code for bitwise and shift operators

    private static long longIntegralValue(Object o) {
        if (o instanceof Long) {
            return (long) o;
        } else if (o instanceof Integer || o instanceof Short || o instanceof Byte) {
            return ((Number) o).longValue();
        } else if (o instanceof Character) {
            return (char) o;
        } else {
            throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
        }
    }

    private static int intIntegralValue(Object o) {
        if (o instanceof Integer || o instanceof Short || o instanceof Byte) {
            return ((Number) o).intValue();
        } else if (o instanceof Character) {
            return (char) o;
        } else {
            throw new ClassCastException("Cannot convert [" + o.getClass().getCanonicalName() + "] to an integral value.");
        }
    }

    // bitwise operators: valid only for integral types

    private static int and(int a, int b) {
        return a & b;
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure both operands are integral types (int, long) before applying bitwise operators
  2. Cast explicitly: longIntegralValue-compatible types only — use ((Number)x).longValue() after checking the type is not Float/Double
  3. Use explicit long types instead of def for both operands
  4. Separate the logic: extract integral values into typed variables before bitwise operations

Example fix

// before
def flags = doc['bitmask'].value;  // Long
def factor = params['factor'];      // Double
def result = flags & factor;

// after
long flags = doc['bitmask'].value;
long factor = (long)(double) params['factor'];
long result = flags & factor;
Defensive patterns

Strategy: validation

Validate before calling

// Before bitwise on def values, verify both are integral
def a = doc['mask'].value;
def b = params['bits'];
if (a instanceof Long && b instanceof Long) {
  return (long) a & (long) b;
} else if ((a instanceof Integer || a instanceof Long) && 
           (b instanceof Integer || b instanceof Long)) {
  return ((Number) a).intValue() & ((Number) b).intValue();
}
throw new IllegalArgumentException('Bitwise operands must be integral');

Type guard

// Check if a def value is safe for long bitwise operations
boolean isLongIntegral(def v) {
  return v instanceof Long || v instanceof Integer || 
         v instanceof Short || v instanceof Byte ||
         v instanceof Character;
}

Prevention

When it happens

Trigger: A Painless script applies a bitwise operator (&, ^, |) to two def-typed values where one operand evaluates to Long at runtime and the other evaluates to Float, Double, Boolean, String, or another non-integral type. The and/xor/or(Object, Object) overload enters the 'left instanceof Long || right instanceof Long' branch and calls longIntegralValue on both operands.

Common situations: def variable holding a float/double value used in a bitwise mask operation; mixing a Long bitmask constant with a floating-point def field; def variable from params that was passed as a Double from JSON; bitwise logic on a field that was dynamically typed as float in the mapping.

Related errors


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