elastic/elasticsearch · error · IllegalArgumentException
Expected a POLYGON, got [{}]
Error message
Expected a POLYGON, got [{}] What it means
parseMultiPolygon (line 760) reads the declared polygon count, then for each element calls parseGeometry (line 767) and checks instanceof Polygon (line 768). A non-Polygon sub-element triggers IllegalArgumentException at line 771. WKB MULTIPOLYGON (type 6/1006) must contain only Polygon elements.
Source
Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java:771
} else {
throw new IllegalArgumentException("Expected a " + ShapeType.LINESTRING + ", got [" + geometry.type() + "]");
}
}
return new MultiLine(Collections.unmodifiableList(lines));
}
private static MultiPolygon parseMultiPolygon(ByteBuffer byteBuffer, boolean coerce) {
final int numPolygons = byteBuffer.getInt();
if (numPolygons == 0) {
return MultiPolygon.EMPTY;
}
final List<Polygon> polygons = new ArrayList<>(numPolygons);
for (int i = 0; i < numPolygons; i++) {
final Geometry geometry = parseGeometry(byteBuffer, coerce);
if (geometry instanceof Polygon p) {
polygons.add(p);
} else {
throw new IllegalArgumentException("Expected a " + ShapeType.POLYGON + ", got [" + geometry.type() + "]");
}
}
return new MultiPolygon(Collections.unmodifiableList(polygons));
}
private static GeometryCollection<Geometry> parseGeometryCollection(ByteBuffer byteBuffer, boolean coerce) {
final int numShapes = byteBuffer.getInt();
if (numShapes == 0) {
return GeometryCollection.EMPTY;
}
final List<Geometry> shapes = new ArrayList<>(numShapes);
for (int i = 0; i < numShapes; i++) {
shapes.add(parseGeometry(byteBuffer, coerce));
}
return new GeometryCollection<>(shapes);
}
View on GitHub (pinned to db6a809a66)
Solutions
- Validate producer output against a reference WKB decoder.
- Ensure MULTIPOLYGON sub-elements carry type code 3 (or 1003 for Z) if you control the producer.
- Re-serialize from a trusted MultiPolygon via WellKnownBinary.toWKB to normalize.
- Catch IllegalArgumentException and route the offending record to a dead-letter queue for inspection.
Example fix
// before
Geometry g = WellKnownBinary.fromWKB(v, false, corruptBytes); // throws: Expected a POLYGON, got [MULTIPOINT]
// after — re-emit from trusted source
Polygon p = new Polygon(new LinearRing(new double[]{0,1,1,0}, new double[]{0,0,1,0}));
MultiPolygon mp = new MultiPolygon(List.of(p));
byte[] clean = WellKnownBinary.toWKB(mp, ByteOrder.LITTLE_ENDIAN);
Geometry g = WellKnownBinary.fromWKB(v, false, clean); Defensive patterns
Strategy: validation
Validate before calling
// No cheap structural pre-check; normalize by re-emitting from trusted source.
byte[] normalize(MultiPolygon mp) { return WellKnownBinary.toWKB(mp, ByteOrder.LITTLE_ENDIAN); } Type guard
// no useful type guard on raw bytes; validate via round-trip
Try / catch
try {
return WellKnownBinary.fromWKB(v, false, wkb);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Expected a POLYGON")) {
// quarantine corrupt MULTIPOLYGON record
}
throw e;
} Prevention
- Re-serialize MULTIPOLYGON from a trusted geometry object before exchange.
- Validate producer output against a reference WKB decoder.
- Ensure MULTIPOLYGON sub-elements carry type code 3 (or 1003 for Z).
When it happens
Trigger: Calling WellKnownBinary.fromWKB with a MULTIPOLYGON WKB whose sub-elements are not Polygon-encoded. Causes: producer bugs allowing mixed-type multi-geometries, buffer corruption, endianness misalignment, or truncation that shifts the sub-element type-code read.
Common situations: Cross-system WKB exchange with emitters that mis-serialize MULTIPOLYGON. Misaligned offsets when slicing a larger buffer. Bit flips in transit/storage. Custom WKB emitters with incorrect sub-element type codes.
Related errors
- Expected a POINT, got [{}]
- Expected a LINESTRING, got [{}]
- Unknown geometry type: {}
- Empty
- Linear ring is not supported by WKB
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/7a66630af946ae2b.
Report an issue: GitHub.