elastic/elasticsearch · error · IllegalArgumentException

Empty

Error message

Empty 

What it means

WellKnownBinary.toWKB serializes a Geometry into the OGC WKB binary format. The Point visitor (line 63) throws IllegalArgumentException when point.isEmpty() is true, because the WKB format has no representation for an empty Point (unlike empty Polygon/Line which serialize as zero-length). This is a format limitation: WKB requires at least one coordinate pair for a Point.

Source

Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java:65

     * Converts the given {@link Geometry} to WKB with the provided {@link ByteOrder}
     */
    public static byte[] toWKB(Geometry geometry, ByteOrder byteOrder) {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            toWKB(geometry, outputStream, ByteBuffer.allocate(8).order(byteOrder));
            return outputStream.toByteArray();
        } catch (IOException ioe) {
            // Should never happen as the only method throwing IOException is ByteArrayOutputStream#close and it is a NOOP
            throw new UncheckedIOException(ioe);
        }
    }

    private static void toWKB(Geometry geometry, ByteArrayOutputStream out, ByteBuffer scratch) {
        out.write(scratch.order() == ByteOrder.BIG_ENDIAN ? 0 : 1);
        geometry.visit(new GeometryVisitor<Void, RuntimeException>() {
            @Override
            public Void visit(Point point) {
                if (point.isEmpty()) {
                    throw new IllegalArgumentException("Empty " + point.type() + " cannot be represented in WKB");
                }
                writeInt(out, scratch, point.hasZ() ? 1001 : 1);
                writeDouble(out, scratch, point.getX());
                writeDouble(out, scratch, point.getY());
                if (point.hasZ()) {
                    writeDouble(out, scratch, point.getZ());
                }
                return null;
            }

            @Override
            public Void visit(Line line) {
                writeInt(out, scratch, line.hasZ() ? 1002 : 2);
                writeInt(out, scratch, line.length());
                for (int i = 0; i < line.length(); ++i) {
                    writeDouble(out, scratch, line.getX(i));
                    writeDouble(out, scratch, line.getY(i));
                    if (line.hasZ()) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Guard before serialization: if (point.isEmpty()) skip or substitute a sentinel, since WKB cannot encode it.
  2. Represent absence with Java null (or an Optional<Point>) in your data model instead of Point.EMPTY when the downstream sink is WKB.
  3. If you control ingestion, normalize empty points to a concrete coordinate (e.g. the field default/centroid) or drop the document.
  4. When serializing collections, filter out empty Point children before toWKB to avoid the throw at the child level.

Example fix

// before
byte[] wkb = WellKnownBinary.toWKB(point, ByteOrder.LITTLE_ENDIAN); // throws on Point.EMPTY

// after
if (point.isEmpty()) {
    return null; // or skip / use sentinel
}
byte[] wkb = WellKnownBinary.toWKB(point, ByteOrder.LITTLE_ENDIAN);
Defensive patterns

Strategy: validation

Validate before calling

boolean canSerializeAsWKB(Geometry g) {
    if (g instanceof Point p && p.isEmpty()) return false;
    if (g instanceof Circle c && c.isEmpty()) return false;
    if (g instanceof Rectangle r && r.isEmpty()) return false;
    if (g instanceof LinearRing) return false;
    if (g instanceof GeometryCollection<?> col) {
        for (Geometry child : col) if (!canSerializeAsWKB(child)) return false;
    }
    return true;
}

Type guard

static boolean isEmptyPoint(Geometry g) { return g instanceof Point p && p.isEmpty(); }

Try / catch

try {
    return WellKnownBinary.toWKB(point, bo);
} catch (IllegalArgumentException e) {
    if (point.isEmpty()) return null; // absent data
    throw e;
}

Prevention

When it happens

Trigger: Calling WellKnownBinary.toWKB(Point.EMPTY, byteOrder), WellKnownBinary.toWKB(new Point(...).emptyVariant(), ...) or passing any Point whose isEmpty() returns true. Also triggered indirectly when serializing a MultiPoint/GeometryCollection that contains an empty Point child (line 110/140 recurse into toWKB for each child).

Common situations: Storing or transmitting optional-location fields where absence was modeled as Point.EMPTY rather than null. Round-tripping GeoJSON that used 'coordinates':[] to represent missing point data. Aggregation pipelines that produce empty points (e.g. centroid of zero-input set) and then attempt WKB serialization for storage/transport.

Related errors


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