elastic/elasticsearch · error · IllegalArgumentException
Unknown geometry type: {}
Error message
Unknown geometry type: {} What it means
Thrown by the Well-Known Binary (WKB) reader path in WellKnownText.parseGeometry(ByteBuffer, StringBuilder). After reading the byte-order flag and a 4-byte int type code from the ByteBuffer, the switch only recognizes OGC SFA type codes 1-7 (and their 1000-series Z variants), plus 17/1017 (Circle) and 18/1018 (BBox). Any other int value falls to the default branch and is rejected as unknown.
Source
Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownText.java:253
switch (type) {
case 1 -> parsePoint(byteBuffer, false, sb);
case 1001 -> parsePoint(byteBuffer, true, sb);
case 2 -> parseLine(byteBuffer, false, sb);
case 1002 -> parseLine(byteBuffer, true, sb);
case 3 -> parsePolygon(byteBuffer, false, sb);
case 1003 -> parsePolygon(byteBuffer, true, sb);
case 4 -> parseMultiPoint(byteBuffer, false, sb);
case 1004 -> parseMultiPoint(byteBuffer, true, sb);
case 5 -> parseMultiLine(byteBuffer, false, sb);
case 1005 -> parseMultiLine(byteBuffer, true, sb);
case 6 -> parseMultiPolygon(byteBuffer, false, sb);
case 1006 -> parseMultiPolygon(byteBuffer, true, sb);
case 7, 1007 -> parseGeometryCollection(byteBuffer, sb);
case 17 -> parseCircle(byteBuffer, false, sb);
case 1017 -> parseCircle(byteBuffer, true, sb);
case 18 -> parseBBox(byteBuffer, false, sb);
case 1018 -> parseBBox(byteBuffer, true, sb);
default -> throw new IllegalArgumentException("Unknown geometry type: " + type);
}
;
}
private static void writeCoordinate(ByteBuffer byteBuffer, boolean hasZ, StringBuilder sb) {
sb.append(byteBuffer.getDouble()).append(SPACE).append(byteBuffer.getDouble());
if (hasZ) {
sb.append(SPACE).append(byteBuffer.getDouble());
}
}
private static void parsePoint(ByteBuffer byteBuffer, boolean hasZ, StringBuilder sb) {
sb.append("POINT").append(SPACE);
sb.append(LPAREN);
writeCoordinate(byteBuffer, hasZ, sb);
sb.append(RPAREN);
}
View on GitHub (pinned to db6a809a66)
Solutions
- Inspect the raw bytes at the ByteBuffer's current position: confirm byte-order flag (0 = big-endian, 1 = little-endian) and that the next 4 bytes decode to a supported type code.
- If the data is EWKB, strip or account for the leading SRID int before passing the buffer; this library expects plain ISO WKB.
- If the data uses SQL/MM curve types (CircularString/CurvePolygon/MultiCurve etc., codes 8-15), convert it to a supported type (LineString/Polygon/MultiLineString) upstream before ingestion.
- Validate the buffer length is at least 5 bytes (1 order + 4 type) before calling, and that the type int is in the supported set.
Example fix
// before: passing EWKB directly, SRID shifts the type field
bb.position(0); // bb still has SRID prefix
WellKnownText.toWKT(bb);
// after: skip the EWKB header (1 byte order + 4 byte SRID) or strip SRID upstream
// ensure buffer is plain ISO WKB with a recognized type code
if (bb.get(0) != 0 && bb.get(0) != 1) {
throw new IllegalArgumentException("expected WKB byte-order flag 0x00 or 0x01");
}
int type = bb.order(bb.get() == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN).getInt();
if (type == 0 || (type >= 8 && type <= 16) || (type >= 1008 && type <= 1016)) {
throw new IllegalArgumentException("unsupported WKB type " + type + "; convert curve/geometry types upstream");
} Defensive patterns
Strategy: validation
Validate before calling
// Validate a WKB ByteBuffer before converting to WKT
private 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
);
static void checkWkbType(ByteBuffer bb) {
ByteBuffer probe = bb.duplicate();
ByteOrder order = probe.get() == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
probe.order(order);
int type = probe.getInt();
if (!SUPPORTED_WKB_TYPES.contains(type)) {
throw new IllegalArgumentException("Unsupported WKB type code: " + type);
}
} Prevention
- Confirm input is plain ISO WKB, not EWKB with an SRID prefix.
- Validate the type int is in the supported set before parsing.
- Reject SQL/MM curve types (8-16) upstream by converting to supported types.
When it happens
Trigger: Calling the WKB-to-WKT conversion (the byteBuffer-based parseGeometry overload) with a ByteBuffer whose position+4..7 bytes encode a type integer outside the supported set {1..7,1001..1007,17,1017,18,1018}. Common offenders: OGC type 0 (Geometry), 8/1008 (CircularString), 9/1009 (Curve), SRID-prefixed WKB (EWKB) where the leading int is an SRID rather than a type, or a truncated/corrupt buffer where the read int is garbage.
Common situations: Ingesting EWKB (PostGIS extended WKB) which prepends an SRID int and shifts the type field; feeding little-endian WKB into a reader expecting big-endian (or vice-versa) so the type int decodes wrong; truncated byte arrays from a partial network read or a serialization bug; a client library emitting newer OGC SQL/MM part 3 curve types (8-15) that this reader predates.
Related errors
- Unknown geometry type:
- When specifying 'Z' or 'M', coordinates must include three v
- maximum nested depth of 1000 exceeded
- coordinate dimensions do not match: {}
- expected word but found: {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/3fe20f7e183dee17.
Report an issue: GitHub.