elastic/elasticsearch · error · IllegalArgumentException
ordered {} are not supported
Error message
ordered {} are not supported What it means
Thrown by the IngestGeoIpMetadata ConstructingObjectParser when the databases field is provided as an ordered array rather than as named objects. declareNamedObjects installs an order-check callback that rejects array-style input; named objects (a JSON object keyed by database id) are required. IllegalArgumentException surfaces during cluster state / API parsing of the ingest geoip metadata.
Source
Thrown at modules/ip-location/src/main/java/org/elasticsearch/ingest/geoip/IngestGeoIpMetadata.java:54
* Holds the ingest-geoip databases that are available in the cluster state.
*/
public final class IngestGeoIpMetadata implements Metadata.ProjectCustom {
public static final String TYPE = "ingest_geoip";
private static final ParseField DATABASES_FIELD = new ParseField("databases");
public static final IngestGeoIpMetadata EMPTY = new IngestGeoIpMetadata(Map.of());
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<IngestGeoIpMetadata, Void> PARSER = new ConstructingObjectParser<>(
TYPE,
a -> new IngestGeoIpMetadata(
((List<DatabaseConfigurationMetadata>) a[0]).stream().collect(Collectors.toMap((m) -> m.database().id(), Function.identity()))
)
);
static {
PARSER.declareNamedObjects(ConstructingObjectParser.constructorArg(), (p, c, n) -> DatabaseConfigurationMetadata.parse(p, n), v -> {
throw new IllegalArgumentException("ordered " + DATABASES_FIELD.getPreferredName() + " are not supported");
}, DATABASES_FIELD);
}
private final Map<String, DatabaseConfigurationMetadata> databases;
public IngestGeoIpMetadata(Map<String, DatabaseConfigurationMetadata> databases) {
this.databases = Map.copyOf(databases);
}
@Override
public String getWriteableName() {
return TYPE;
}
@Override
public TransportVersion getMinimalSupportedVersion() {
return TransportVersion.minimumCompatible();
}View on GitHub (pinned to db6a809a66)
Solutions
- Send databases as a JSON object keyed by database id, e.g. {"databases": {"mydb": {...}}} rather than [{"name":"mydb",...}].
- If integrating via JSON, configure the serializer to emit maps as objects and to skip null keys.
- Validate the request body shape against the rest-api-spec before sending.
Example fix
// before
{"databases": [{"name":"city","md5":"..."}]}
// after
{"databases": {"city": {"name":"city","md5":"..."}}} Defensive patterns
Strategy: validation
Validate before calling
// before sending, ensure databases is a JSON object, not an array
Object databases = body.get("databases");
if (databases instanceof List) {
throw new IllegalArgumentException("databases must be a JSON object keyed by id, not an array");
} Prevention
- Always serialize the databases field as a JSON object keyed by database id.
- Configure JSON serializers to render Maps as objects, never as arrays.
- Validate request bodies against the rest-api-spec before submission.
- Add integration tests that send the documented object shape.
When it happens
Trigger: Parsing a IngestGeoIpMetadata JSON where DATABASES_FIELD is a JSON array; declareNamedObjects' third lambda fires with the rejection message.
Common situations: Hand-crafted API request or external automation sending databases as a list; a serialization library defaulting a Map to an array; version skew where an older client sends array form.
Related errors
- Failed to parse content of branches.json
- expected data to start with an object
- Exactly one provider object must be specified, but [{}] were
- repeated attribute key [{}]
- Failed to parse value [{}] as only [true] or [false] are all
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/8bb9dce21a42794b.
Report an issue: GitHub.