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

  1. 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.
  2. Check buffer length is at least 5 and that the type int is in the supported set before calling fromWKB.
  3. Confirm producer and consumer agree on byte order; if the producer emits EWKB, strip the EWKB header/SRID extension first.
  4. 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

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


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