elastic/elasticsearch · error · ParseException

Parameter [{}] must be a numeric type

Error message

Parameter [{}] must be a numeric type

What it means

Thrown in bindFromParams() when a parameter value is not an instance of Number. This function is called during variable binding for sort, score, aggregation, field, and terms-set scripts when a variable name matches a key in the params map. If the corresponding value is not numeric (e.g., String, Boolean, null), a ParseException is thrown.

Source

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

            }
        } else {
            throw new ParseException("Field [" + fieldname + "] must be numeric, date, or geopoint", 5);
        }
        return valueSource;
    }

    // TODO: document and/or error if params contains _score?
    // NOTE: by checking for the variable in params first, it allows masking document fields with a global constant,
    // but if we were to reverse it, we could provide a way to supply dynamic defaults for documents missing the field?
    private static void bindFromParams(@Nullable final Map<String, Object> params, final SimpleBindings bindings, final String variable)
        throws ParseException {
        // NOTE: by checking for the variable in vars first, it allows masking document fields with a global constant,
        // but if we were to reverse it, we could provide a way to supply dynamic defaults for documents missing the field?
        Object value = params.get(variable);
        if (value instanceof Number) {
            bindings.add(variable, DoubleValuesSource.constant(((Number) value).doubleValue()));
        } else {
            throw new ParseException("Parameter [" + variable + "] must be a numeric type", 0);
        }
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Pass numeric values as JSON numbers (unquoted): {"factor": 2} not {"factor": "2"}.
  2. In programmatic API usage, ensure param values are Java Number types (Double, Integer, Long) before passing to the script.
  3. Validate the params map before execution: check each value is instanceof Number.
  4. If a string must be used, convert it to a number in the application layer before submitting the script.

Example fix

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

Strategy: type-guard

Validate before calling

// Validate all param values are numeric before passing to the script
for (Map.Entry<String, Object> entry : params.entrySet()) {
    if (!(entry.getValue() instanceof Number)) {
        throw new IllegalArgumentException(
            "Parameter [" + entry.getKey() + "] must be numeric but was: " + entry.getValue()
        );
    }
}

Type guard

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

// Filter params to only numeric values before passing to the script:
Map<String, Object> safeParams = new HashMap<>();
params.forEach((k, v) -> {
    if (isNumeric(v)) safeParams.put(k, v);
    else throw new IllegalArgumentException("Param " + k + " must be numeric");
});

Try / catch

try {
    engine.compile(scriptName, scriptSource, context, params);
} catch (ScriptException e) {
    if (e.getCause() instanceof ParseException
        && e.getCause().getMessage().contains("must be a numeric type")) {
        String paramName = extractParamName(e.getCause().getMessage());
        logger.error("Param '{}' must be numeric — check JSON value type", paramName);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a non-numeric param value in a script that the expression references as a variable. For example, {"source": "factor * doc['price'].value", "params": {"factor": "2"}} — factor is a string "2" not a number 2.

Common situations: JSON serialization producing quoted strings for numbers; programmatic param construction using String types; Boolean or null values passed where numbers are expected; deserializing params from an external config that treats all values as strings.

Related errors


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