elastic/elasticsearch · error · IllegalArgumentException

array in field [{}] should only contain strings

Error message

array in field [{}] should only contain strings

What it means

Thrown by GeoIpProcessor.execute when the source field is a List, but one of its elements is not a String. The processor iterates list elements and requires each to be a string IP address for lookup.

Source

Thrown at modules/ingest-ip-location/src/main/java/org/elasticsearch/ingest/iplocation/GeoIpProcessor.java:120

        }

        if (ip instanceof String ipString) {
            Map<String, Object> data = ipDataLookup.lookup(ipString);
            if (data == null) {
                if (ignoreMissing == false) {
                    tag(document, type, databaseFile);
                }
                return document;
            }
            if (data.isEmpty() == false) {
                writeGeoIpData(document, targetField, data);
            }
        } else if (ip instanceof List<?> ipList) {
            boolean match = false;
            List<Map<String, Object>> dataList = new ArrayList<>(ipList.size());
            for (Object ipAddr : ipList) {
                if (ipAddr instanceof String == false) {
                    throw new IllegalArgumentException("array in field [" + field + "] should only contain strings");
                }
                Map<String, Object> data = ipDataLookup.lookup((String) ipAddr);
                if (data == null) {
                    if (ignoreMissing == false) {
                        tag(document, type, databaseFile);
                    }
                    return document;
                }
                if (data.isEmpty()) {
                    dataList.add(null);
                    continue;
                }
                if (firstOnly) {
                    writeGeoIpData(document, targetField, data);
                    return document;
                }
                match = true;
                dataList.add(data);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure the array contains only string IP addresses by filtering upstream.
  2. Use a script processor to coerce or remove non-string elements before geoip.
  3. Split the array or map elements to a clean string-only array upstream.

Example fix

// before: client_ip = ["1.2.3.4", 12345]
{
  "geoip": { "field": "client_ip", "target_field": "geo" }
}
// after: sanitize upstream
{
  "script": { "source": "ctx.client_ip = ctx.client_ip?.findAll { it instanceof String }" } },
{
  "geoip": { "field": "client_ip", "target_field": "geo" }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Filter the array to strings only before geoip (via script processor)
// ctx.client_ip = ctx.client_ip?.findAll { it instanceof String }
List<?> list = document.getFieldValue("client_ip", List.class, true);
if (list != null && list.stream().anyMatch(e -> !(e instanceof String))) {
    // sanitize upstream
}

Type guard

boolean isStringArray(IngestDocument doc, String field) {
    Object v = doc.getFieldValue(field, Object.class, true);
    if (!(v instanceof List<?> l)) return false;
    return l.stream().allMatch(e -> e == null || e instanceof String);
}

Try / catch

try {
    // run geoip processor on array field
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("should only contain strings")) {
        // add a script processor to filter non-string elements
    } else { throw e; }
}

Prevention

When it happens

Trigger: The configured field is an array containing non-string elements (e.g., numbers, nested objects, booleans) mixed with or instead of IP strings.

Common situations: Source data where IP arrays also include numeric IDs or metadata objects. Schema drift where the field type changed. Mixed-content arrays from uncontrolled upstream sources.

Related errors


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