elastic/elasticsearch · error · IllegalArgumentException

Error using {}. Executable expressions scripts can only proc

Error message

Error using {}. Executable expressions scripts can only process numbers.  The variable [{}] is not a number.

What it means

Thrown inside BucketAggregationScript.execute() when a parameter value is not an instance of Number. The expression engine can only process numeric values; it checks value instanceof Number and throws IllegalArgumentException if the check fails, naming the offending variable.

Source

Thrown at modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java:197

                functionValuesArray[i] = new ReplaceableConstDoubleValues();
                functionValuesMap.put(expr.variables[i], functionValuesArray[i]);
            }
            return new BucketAggregationScript(parameters) {
                @Override
                public Double execute() {
                    getParams().forEach((name, value) -> {
                        ReplaceableConstDoubleValues placeholder = functionValuesMap.get(name);
                        if (placeholder == null) {
                            throw new IllegalArgumentException(
                                "Error using "
                                    + expr
                                    + ". "
                                    + "The variable ["
                                    + name
                                    + "] does not exist in the executable expressions script."
                            );
                        } else if (value instanceof Number == false) {
                            throw new IllegalArgumentException(
                                "Error using "
                                    + expr
                                    + ". "
                                    + "Executable expressions scripts can only process numbers."
                                    + "  The variable ["
                                    + name
                                    + "] is not a number."
                            );
                        } else {
                            placeholder.setValue(((Number) value).doubleValue());
                        }
                    });
                    try {
                        return expr.evaluate(functionValuesArray);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure all param values are JSON numbers (unquoted), not strings: use {"factor": 1.5} not {"factor": "1.5"}.
  2. If generating params programmatically, cast or convert values to numeric types before passing them.
  3. Validate the params map type before script execution — reject any value that is not an instance of Number.
  4. If the value must be a string (e.g., a field name), use Painless instead of expression.

Example fix

// before: factor is a string
"params": {"factor": "1.5"}
// after: factor is a number
"params": {"factor": 1.5}
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate all param values are numeric before passing to the script
Map<String, Object> params = new HashMap<>();
for (Map.Entry<String, Object> entry : rawParams.entrySet()) {
    if (entry.getValue() instanceof Number == false) {
        throw new IllegalArgumentException(
            "Param '" + entry.getKey() + "' must be numeric, got: " + entry.getValue().getClass()
        );
    }
    params.put(entry.getKey(), entry.getValue());
}

Type guard

// Type guard for numeric params
static boolean isNumericParam(Object value) {
    return value instanceof Number;
}

// Usage:
for (Map.Entry<String, Object> e : params.entrySet()) {
    if (!isNumericParam(e.getValue())) {
        throw new IllegalArgumentException("Non-numeric param: " + e.getKey());
    }
}

Try / catch

try {
    Double result = bucketScript.execute();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("not a number")) {
        logger.error("Non-numeric param in bucket script: {}", e.getMessage());
        // Fix the param type and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a non-numeric param (String, Boolean, List, Map) to a bucket aggregation expression script. For example, params: {"factor": "1.5"} where the value is a String instead of a number.

Common situations: JSON parsing produces String for values that should be numeric (e.g., quoted numbers in the params block); dynamic param construction using the wrong type; migrating from Painless where type coercion was automatic.

Related errors


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