{"record":{"id":"b56d58c39743d05c","repo":"elastic/elasticsearch","slug":"parameter-must-be-a-numeric-type","errorCode":null,"errorMessage":"Parameter [{}] must be a numeric type","messagePattern":"Parameter \\[(.+?)\\] must be a numeric type","errorType":"validation","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java","lineNumber":498,"sourceCode":"            }\n        } else {\n            throw new ParseException(\"Field [\" + fieldname + \"] must be numeric, date, or geopoint\", 5);\n        }\n        return valueSource;\n    }\n\n    // TODO: document and/or error if params contains _score?\n    // NOTE: by checking for the variable in params first, it allows masking document fields with a global constant,\n    // but if we were to reverse it, we could provide a way to supply dynamic defaults for documents missing the field?\n    private static void bindFromParams(@Nullable final Map<String, Object> params, final SimpleBindings bindings, final String variable)\n        throws ParseException {\n        // NOTE: by checking for the variable in vars first, it allows masking document fields with a global constant,\n        // but if we were to reverse it, we could provide a way to supply dynamic defaults for documents missing the field?\n        Object value = params.get(variable);\n        if (value instanceof Number) {\n            bindings.add(variable, DoubleValuesSource.constant(((Number) value).doubleValue()));\n        } else {\n            throw new ParseException(\"Parameter [\" + variable + \"] must be a numeric type\", 0);\n        }\n    }\n}\n","sourceCodeStart":480,"sourceCodeEnd":502,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java#L480-L502","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass numeric values as JSON numbers (unquoted): {\"factor\": 2} not {\"factor\": \"2\"}.","In programmatic API usage, ensure param values are Java Number types (Double, Integer, Long) before passing to the script.","Validate the params map before execution: check each value is instanceof Number.","If a string must be used, convert it to a number in the application layer before submitting the script."],"exampleFix":"// before: factor is a string\n\"params\": {\"factor\": \"2\"}\n// after: factor is a number\n\"params\": {\"factor\": 2}","handlingStrategy":"type-guard","validationCode":"// Validate all param values are numeric before passing to the script\nfor (Map.Entry<String, Object> entry : params.entrySet()) {\n    if (!(entry.getValue() instanceof Number)) {\n        throw new IllegalArgumentException(\n            \"Parameter [\" + entry.getKey() + \"] must be numeric but was: \" + entry.getValue()\n        );\n    }\n}","typeGuard":"// Type guard for numeric params\nstatic boolean isNumeric(Object value) {\n    return value instanceof Number;\n}\n\n// Filter params to only numeric values before passing to the script:\nMap<String, Object> safeParams = new HashMap<>();\nparams.forEach((k, v) -> {\n    if (isNumeric(v)) safeParams.put(k, v);\n    else throw new IllegalArgumentException(\"Param \" + k + \" must be numeric\");\n});","tryCatchPattern":"try {\n    engine.compile(scriptName, scriptSource, context, params);\n} catch (ScriptException e) {\n    if (e.getCause() instanceof ParseException\n        && e.getCause().getMessage().contains(\"must be a numeric type\")) {\n        String paramName = extractParamName(e.getCause().getMessage());\n        logger.error(\"Param '{}' must be numeric — check JSON value type\", paramName);\n    }\n    throw e;\n}","preventionTips":["Pass numeric values as JSON numbers (unquoted) in REST API calls.","In application code, enforce Number types when building the params map.","Add a validation layer for params coming from external configuration.","Be especially careful with deserialized config where all values may be strings."],"tags":["expression","script","params","type-error","numeric-required"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}