elastic/elasticsearch · error · ClassCastException

cannot cast null java.lang.String to char

Error message

cannot cast null java.lang.String to char

What it means

Utility.StringTochar is the runtime helper Painless emits when a script casts a String value to char. If the String is null, this ClassCastException is thrown with the literal type names (java.lang.String and char). This fires at script execution time, not compile time.

Source

Thrown at modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java:24

 * your election, the "Elastic License 2.0", the "GNU Affero General Public
 * License v3.0 only", or the "Server Side Public License, v 1".
 */

package org.elasticsearch.painless;

/**
 * A set of methods for non-native boxing and non-native
 * exact math operations used at both compile-time and runtime.
 */
public class Utility {

    public static String charToString(final char value) {
        return String.valueOf(value);
    }

    public static char StringTochar(final String value) {
        if (value == null) {
            throw new ClassCastException(
                "cannot cast " + "null " + String.class.getCanonicalName() + " to " + char.class.getCanonicalName()
            );
        }

        if (value.length() != 1) {
            throw new ClassCastException(
                "cannot cast " + String.class.getCanonicalName() + " with length not equal to one to " + char.class.getCanonicalName()
            );
        }

        return value.charAt(0);
    }

    private Utility() {}
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Null-check the String before casting to char.
  2. Default the source value with an elvis/conditional: str == null ? '\0' : (char)str.
  3. Ensure the underlying field/mapping cannot produce null for the scripted path.

Example fix

// before
char c = (char)doc['initial'].value; // null -> 1348
// after
String s = doc['initial'].value;
char c = s == null ? '\\0' : (char)s;
Defensive patterns

Strategy: validation

Validate before calling

// Inside the Painless script, guard before casting:
// String s = doc['initial'].value;
// if (s == null) { /* handle */ } else { char c = (char)s; }

Type guard

// Painless-side guard
String s = doc['initial'].value;
if (s != null && s.length() == 1) { /* safe to cast */ }

Try / catch

// In Java calling code, catch ClassCastException from script execution:
try {
    scriptService.run(script, context, vars);
} catch (ScriptException e) {
    if (e.getCause() instanceof ClassCastException ce && ce.getMessage().contains("null") && ce.getMessage().contains("char")) {
        log.warn("null String-to-char in script");
    }
    throw e;
}

Prevention

When it happens

Trigger: A Painless script performs an explicit cast '(char)someString' or assigns a String to a char variable where the String value is null at runtime — e.g. reading a missing document field that returns null.

Common situations: Casting doc['field'].value (which can be null for missing fields) to char; user-supplied script params that are null; runtime field evaluating null string data.

Related errors


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