elastic/elasticsearch · error · IllegalArgumentException

holes must have the same number of dimensions as the polygon

Error message

holes must have the same number of dimensions as the polygon

What it means

writeWKBPolygon (line 321) reads the outer ring and any holes from WKT, then at lines 341-345 verifies every ring has the same Z dimensionality as the first (outer) ring. If any hole's hasZ differs from the shell's hasZ, it throws IllegalArgumentException. WKB polygon encoding (type 3 or 1003) is single-dimensionality per geometry — a polygon cannot mix 2D and 3D rings.

Source

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

        boolean explicitZ,
        GeometryValidator validator
    ) throws IOException, ParseException {
        if (WellKnownText.nextEmptyOrOpen(stream).equals(WellKnownText.EMPTY)) {
            writeInt(out, scratch, 3);
            writeInt(out, scratch, 0);
            return;
        }
        List<CoordsList> rings = new ArrayList<>();
        WellKnownText.nextOpener(stream);
        rings.add(wktReadRing(stream, coerce, validator));
        while (WellKnownText.nextCloserOrComma(stream).equals(WellKnownText.COMMA)) {
            WellKnownText.nextOpener(stream);
            rings.add(wktReadRing(stream, coerce, validator));
        }
        boolean hasZ = rings.isEmpty() == false && rings.get(0).hasZ();
        for (CoordsList ring : rings) {
            if (ring.hasZ() != hasZ) {
                throw new IllegalArgumentException("holes must have the same number of dimensions as the polygon");
            }
        }
        WellKnownText.checkZorMAttribute(explicitZ, hasZ);
        writeInt(out, scratch, hasZ ? 1003 : 3);
        writeInt(out, scratch, rings.size());
        for (CoordsList ring : rings) {
            writeInt(out, scratch, ring.size());
            writeCoordinateList(out, scratch, ring);
        }
    }

    private static void writeWKBMultiPoint(
        StreamTokenizer stream,
        ByteArrayOutputStream out,
        ByteBuffer scratch,
        boolean explicitZ,
        GeometryValidator validator
    ) throws IOException, ParseException {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Make dimensionality consistent across all rings of the polygon: either add Z to every ring or remove Z from every ring.
  2. Validate before serialization: parse the WKT, check each ring's Z presence, and normalize (strip Z or backfill) before fromWKT.
  3. Configure your authoring tool to enforce uniform dimensionality per polygon.

Example fix

// before — mixed dimensions
fromWKT("POLYGON((0 0, 10 0, 10 10, 0 0), (1 1 5, 2 1 5, 2 2 5, 1 1 5))", BO, false, v);
// throws: holes must have the same number of dimensions as the polygon

// after — all rings 2D
fromWKT("POLYGON((0 0, 10 0, 10 10, 0 0), (1 1, 2 1, 2 2, 1 1))", BO, false, v);
Defensive patterns

Strategy: validation

Validate before calling

// after parsing rings into CoordsList-like structures:
boolean ringsConsistentZ(List<boolean> ringHasZ) {
    Boolean first = null;
    for (boolean z : ringHasZ) {
        if (first == null) first = z;
        else if (z != first) return false;
    }
    return true;
}

Type guard

// structural: confirm outer and all holes share hasZ before fromWKT
static boolean polygonRingsUniformZ(String wkt) {
    // crude check: count Z triples vs pairs per ring; better: parse to Geometry first
    return true; // implement per-ring Z-presence scan
}

Try / catch

try {
    return WellKnownBinary.fromWKT(wkt, bo, coerce, v);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("holes must have the same number of dimensions")) {
        // normalize: strip Z from all rings, then retry
    } else throw e;
}

Prevention

When it happens

Trigger: Calling WellKnownBinary.fromWKT with a POLYGON WKT whose outer ring and hole(s) disagree on Z presence, e.g. outer 'POLYGON((0 0, 10 0, 10 10, 0 0), (1 1 5, 2 1 5, 2 2 5, 1 1 5))' (outer 2D, hole 3D) or the reverse. Reached during direct WKT-to-WKB conversion.

Common situations: Hand-authored WKT where the author added altitude to holes but not the shell (or vice versa). Merging polygon data from sources with inconsistent dimensionality. Edit tools that append Z to selected rings. Programmatic polygon builders that conditionally add Z per-ring.

Related errors


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