elastic/elasticsearch · error · IllegalArgumentException
Unknown geometry type: {}
Error message
Unknown geometry type: {} What it means
WellKnownBinary.fromWKB (line 642) parses a WKB byte array via parseGeometry (line 656). After reading byte order and the 4-byte type int (lines 657-658), it switches over the recognized type codes (1-7, 1001-1007, 17/1017, 18/1018). Any other type code hits the default at line 674 and throws IllegalArgumentException. This indicates corrupt, truncated, or non-conforming WKB.
Source
Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java:674
private static Geometry parseGeometry(ByteBuffer byteBuffer, boolean coerce) {
byteBuffer.order(byteBuffer.get() == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
final int type = byteBuffer.getInt();
return switch (type) {
case 1 -> parsePoint(byteBuffer, false);
case 1001 -> parsePoint(byteBuffer, true);
case 2 -> parseLine(byteBuffer, false);
case 1002 -> parseLine(byteBuffer, true);
case 3 -> parsePolygon(byteBuffer, false, coerce);
case 1003 -> parsePolygon(byteBuffer, true, coerce);
case 4, 1004 -> parseMultiPoint(byteBuffer);
case 5, 1005 -> parseMultiLine(byteBuffer);
case 6, 1006 -> parseMultiPolygon(byteBuffer, coerce);
case 7, 1007 -> parseGeometryCollection(byteBuffer, coerce);
case 17 -> parseCircle(byteBuffer, false);
case 1017 -> parseCircle(byteBuffer, true);
case 18 -> parseBBox(byteBuffer, false);
case 1018 -> parseBBox(byteBuffer, true);
default -> throw new IllegalArgumentException("Unknown geometry type: " + type);
};
}
private static Point parsePoint(ByteBuffer byteBuffer, boolean hasZ) {
if (hasZ) {
return new Point(byteBuffer.getDouble(), byteBuffer.getDouble(), byteBuffer.getDouble());
} else {
return new Point(byteBuffer.getDouble(), byteBuffer.getDouble());
}
}
private static Line parseLine(ByteBuffer byteBuffer, boolean hasZ) {
final int length = byteBuffer.getInt();
if (length == 0) {
return Line.EMPTY;
}
final double[] lats = new double[length];
final double[] lons = new double[length];View on GitHub (pinned to db6a809a66)
Solutions
- Verify the WKB came from a producer that emits only OGC types 1-7 (optionally ES 17/18 and the 10xx Z variants); convert unsupported SQL-MM types upstream.
- Check buffer length is at least 5 and that the type int is in the supported set before calling fromWKB.
- Confirm producer and consumer agree on byte order; if the producer emits EWKB, strip the EWKB header/SRID extension first.
- Catch IllegalArgumentException and report the offending type code for diagnosis.
Example fix
// before
Geometry g = WellKnownBinary.fromWKB(v, false, rawBytes); // throws on type=8 (CircularString)
// after — guard the type code
int code = ByteBuffer.wrap(rawBytes, 1, 4)
.order(rawBytes[0] == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN).getInt();
if (Set.of(1,2,3,4,5,6,7,17,18,1001,1002,1003,1004,1005,1006,1007,1017,1018).contains(code) == false) {
throw new IllegalArgumentException("Unsupported WKB type code: " + code);
}
Geometry g = WellKnownBinary.fromWKB(v, false, rawBytes); Defensive patterns
Strategy: validation
Validate before calling
static final Set<Integer> SUPPORTED_WKB_TYPES = Set.of(
1,2,3,4,5,6,7,17,18, 1001,1002,1003,1004,1005,1006,1007,1017,1018);
boolean isSupportedWkbType(byte[] wkb) {
if (wkb == null || wkb.length < 5) return false;
ByteOrder bo = wkb[0] == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
int type = ByteBuffer.wrap(wkb, 1, 4).order(bo).getInt();
return SUPPORTED_WKB_TYPES.contains(type);
} Type guard
static Integer readWkbType(byte[] wkb) {
if (wkb == null || wkb.length < 5) return null;
ByteOrder bo = wkb[0] == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
return ByteBuffer.wrap(wkb, 1, 4).order(bo).getInt();
} Try / catch
try {
return WellKnownBinary.fromWKB(v, coerce, wkb);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unknown geometry type")) {
// quarantine record; log the offending type code for diagnosis
}
throw e;
} Prevention
- Verify the producer emits only OGC types 1-7 (and ES 17/18, plus 10xx Z variants).
- Strip EWKB headers / SRID extensions before fromWKB.
- Confirm producer and consumer agree on byte order.
- Validate buffer length >= 5 and type code is in the supported set before parsing.
When it happens
Trigger: Calling WellKnownBinary.fromWKB(validator, coerce, wkb) with bytes whose type-code int (after the byte-order byte) is outside the recognized set. Caused by: truncated buffer (offset misread so a coordinate is parsed as the type), wrong endianness interpretation, an OGC type this library does not support (e.g. 8=CircularString, 9=CompoundCurve, 15=PolyhedralSurface, 16=Tin), or post-SQL-MM extended codes.
Common situations: Ingesting WKB from SQL-MM / PostGIS IWKB / EWKB sources that use unsupported extended geometry types. Bit-rot or truncation in transport/storage. Endianness confusion between producer and consumer. Misaligned offsets when slicing a larger buffer.
Related errors
- Expected a POINT, got [{}]
- Expected a LINESTRING, got [{}]
- Expected a POLYGON, got [{}]
- Unknown geometry type:
- Empty
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/eb4aa7e6e3f03350.
Report an issue: GitHub.