elastic/elasticsearch · error · ParseException

Field [{}] must be numeric, date, or geopoint

Error message

Field [{}] must be numeric, date, or geopoint

What it means

Thrown in getDocValueSource() when the field exists in the mapping but its type is not numeric, date, or geo_point. The expression engine requires fields to be one of these types because it operates on DoubleValues; text, keyword, boolean, ip, and other types cannot provide numeric double values.

Source

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

                    valueSource = DateObject.getMethod(fieldData, fieldname, methodname);
                }
            } else {
                // date field itself
                if (methodname == null) {
                    valueSource = DateField.getVariable(fieldData, fieldname, variablename);
                } else {
                    valueSource = DateField.getMethod(fieldData, fieldname, methodname);
                }
            }
        } else if (fieldData instanceof IndexNumericFieldData) {
            // number
            if (methodname == null) {
                valueSource = NumericField.getVariable(fieldData, fieldname, variablename);
            } else {
                valueSource = NumericField.getMethod(fieldData, fieldname, methodname);
            }
        } 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. Check the field type in the mapping: GET <index>/_mapping — confirm it is integer, long, float, double, scaled_float, date, or geo_point.
  2. If the field is text/keyword, create a numeric sub-field or use a multi-field with a numeric type, then reindex.
  3. For boolean fields, there is no direct expression support — use Painless or convert to numeric (0/1) at index time.
  4. Ensure geo fields are type geo_point, not geo_shape.

Example fix

// before: 'category' is a keyword field — expression cannot use it
"source": "doc['category'].value"
// after: use a numeric field instead
GET my-index/_mapping  // verify which fields are numeric
"source": "doc['category_id'].value"
Defensive patterns

Strategy: validation

Validate before calling

// Verify field types are supported before using them in expressions
GET my-index/_mapping
// Supported types: integer, long, float, double, scaled_float, date, geo_point
// Unsupported: text, keyword, boolean, ip, binary, object, nested, geo_shape
// Check each doc['fieldname'] in the expression against the mapping type

Try / catch

try {
    engine.compile(scriptName, scriptSource, context, params);
} catch (ScriptException e) {
    if (e.getCause() instanceof ParseException
        && e.getCause().getMessage().contains("must be numeric, date, or geopoint")) {
        String fieldName = extractFieldName(e.getCause().getMessage());
        logger.error("Field '{}' is not numeric/date/geo_point — cannot use in expression", fieldName);
    }
    throw e;
}

Prevention

When it happens

Trigger: Expression references doc['description'].value where 'description' is type text, or doc['active'].value where 'active' is type boolean. The field exists (so error 1235 doesn't fire) but the type check fails.

Common situations: Using an expression on a text/keyword field instead of a numeric sub-field; field type changed during reindex; assuming a field is numeric when it's actually scaled_float stored as string; geo_shape field mistaken for geo_point.

Related errors


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