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

  1. 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.
  2. If the data is EWKB, strip or account for the leading SRID int before passing the buffer; this library expects plain ISO WKB.
  3. 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.
  4. 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

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


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