elastic/elasticsearch · error · IllegalArgumentException

Empty CIRCLE cannot be represented in WKB

Error message

Empty CIRCLE cannot be represented in WKB

What it means

writeWKBCircle (line 500) is the WKT-to-WKB direct converter for the CIRCLE type (an ES extension). At line 507 it throws IllegalArgumentException when the token following 'CIRCLE' is 'EMPTY', because the WKB circle encoding (type 17/1017) requires center x, y, radius (and optional z) — none meaningful for an empty circle.

Source

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

            }
        }
        WellKnownText.checkZorMAttribute(explicitZ, hasZ);
        writeInt(out, scratch, hasZ ? 1007 : 7);
        writeInt(out, scratch, subGeometries.size());
        for (byte[] subGeom : subGeometries) {
            out.write(subGeom, 0, subGeom.length);
        }
    }

    private static void writeWKBCircle(
        StreamTokenizer stream,
        ByteArrayOutputStream out,
        ByteBuffer scratch,
        boolean explicitZ,
        GeometryValidator validator
    ) throws IOException, ParseException {
        if (WellKnownText.nextEmptyOrOpen(stream).equals(WellKnownText.EMPTY)) {
            throw new IllegalArgumentException("Empty CIRCLE cannot be represented in WKB");
        }
        double x = WellKnownText.nextNumber(stream);
        double y = WellKnownText.nextNumber(stream);
        // WKT circle format: (x y r [z]) — radius comes before optional z
        double r = WellKnownText.nextNumber(stream);
        double z = Double.NaN;
        if (WellKnownText.isNumberNext(stream)) {
            z = WellKnownText.nextNumber(stream);
        }
        WellKnownText.nextCloser(stream);
        validator.validateCoordinate(x, y, z);
        boolean hasZ = Double.isNaN(z) == false;
        WellKnownText.checkZorMAttribute(explicitZ, hasZ);
        // WKB circle format: type x y [z] r — z comes before radius
        writeInt(out, scratch, hasZ ? 1017 : 17);
        writeDouble(out, scratch, x);
        writeDouble(out, scratch, y);
        if (hasZ) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Detect and skip 'CIRCLE EMPTY' (case-insensitive, trimmed) before fromWKT, treating it as absent data.
  2. Normalize empty circles to a concrete value or to a null/absent document upstream.
  3. If you must preserve emptiness, store WKT rather than WKB, or use a sentinel schema field.

Example fix

// before
byte[] wkb = WellKnownBinary.fromWKT("CIRCLE EMPTY", BO, false, v); // throws

// after
String wkt = wktInput.trim();
if (wkt.equalsIgnoreCase("CIRCLE EMPTY")) {
    return null;
}
byte[] wkb = WellKnownBinary.fromWKT(wkt, BO, false, v);
Defensive patterns

Strategy: validation

Validate before calling

boolean isCircleEmpty(String wkt) {
    return wkt.trim().equalsIgnoreCase("CIRCLE EMPTY");
}

Type guard

static boolean isEmptyCircleWkt(String wkt) {
    return wkt.trim().equalsIgnoreCase("CIRCLE EMPTY");
}

Try / catch

try {
    return WellKnownBinary.fromWKT(wkt, bo, coerce, v);
} catch (IllegalArgumentException e) {
    if (wkt.trim().equalsIgnoreCase("CIRCLE EMPTY")) return null;
    throw e;
}

Prevention

When it happens

Trigger: Calling WellKnownBinary.fromWKT("CIRCLE EMPTY", byteOrder, coerce[, validator]). The trigger is the literal WKT token 'CIRCLE' followed by 'EMPTY'.

Common situations: Indexing optional-radius features where the source represents absence as 'CIRCLE EMPTY'. Round-tripping data that used WKT's empty-circle syntax into a WKB sink. Ingest pipelines that pass through user-supplied circle WKT without normalizing empties.

Related errors


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