elastic/elasticsearch · error · IllegalArgumentException

LinearRing cannot have less than 4 points

Error message

LinearRing cannot have less than 4 points

What it means

Thrown by StreamingGeometrySimplifier.produceLinearRing when the simplifier has accumulated between 1 and 3 points. A LinearRing (per OGC/ESRI semantics used by Elasticsearch) requires at least 4 points, where the first and last are the same coordinate. Fewer than 4 cannot form a closed ring.

Source

Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/simplify/StreamingGeometrySimplifier.java:351

            this(maxPoints, calculator, null);
        }

        public PolygonSimplifier(int maxPoints, SimplificationErrorCalculator calculator, Monitor monitor) {
            super("Polygon", maxPoints, calculator, monitor);
        }

        @Override
        public Polygon produce() {
            return new Polygon(StreamingGeometrySimplifier.produceLinearRing(this));
        }
    }

    static LinearRing produceLinearRing(StreamingGeometrySimplifier<?> simplifier) {
        if (simplifier.length < 1) {
            throw new IllegalArgumentException("No points have been consumed");
        }
        if (simplifier.length < 4) {
            throw new IllegalArgumentException("LinearRing cannot have less than 4 points");
        }
        double[] x = new double[simplifier.length];
        double[] y = new double[simplifier.length];
        for (int i = 0; i < simplifier.length; i++) {
            x[i] = simplifier.points[i].x;
            y[i] = simplifier.points[i].y;
        }
        if (x[simplifier.length - 1] != x[0] || y[simplifier.length - 1] != y[0]) {
            String inequality = "(" + x[0] + " " + y[0] + ") != (" + x[simplifier.length - 1] + " " + y[simplifier.length - 1] + ")";
            throw new IllegalArgumentException("LinearRing cannot have first and last points differ: " + inequality);
        }
        return new LinearRing(x, y);
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Raise maxPoints so the simplifier cannot collapse the ring below 4 vertices.
  2. Validate the source polygon has >= 4 vertices before simplifying; reject or pass through degenerate inputs.
  3. If you are constructing the simplifier by hand, ensure at least 4 consume() calls (with first == last) before produce().

Example fix

// before
var s = new StreamingGeometrySimplifier.PolygonSimplifier(3, calc, monitor); // maxPoints too low
for (double[] pt : pts) s.consume(pt[0], pt[1]);
Polygon p = s.produce(); // can collapse to < 4

// after
var s = new StreamingGeometrySimplifier.PolygonSimplifier(Math.max(4, desiredMax), calc, monitor);
for (double[] pt : pts) s.consume(pt[0], pt[1]);
Polygon p = s.length >= 4 ? s.produce() : preserveOriginal();
Defensive patterns

Strategy: validation

Validate before calling

int maxPoints = Math.max(4, desiredMax);
if (sourceRing.length < 4) throw new IllegalArgumentException("source ring has fewer than 4 points");
var s = new StreamingGeometrySimplifier.PolygonSimplifier(maxPoints, calc, monitor);
for (int i = 0; i < sourceRing.length; i++) s.consume(sourceRing[i][0], sourceRing[i][1]);
return s.produce();

Prevention

When it happens

Trigger: Consuming 1, 2, or 3 points into a PolygonSimplifier and then calling produce(). This check fires after the length < 1 check, so it specifically catches the 'some points but not enough' case.

Common situations: Degenerate input polygons with only two or three distinct vertices; a bug in upstream geometry construction that produced a triangle ring without the closing duplicate; simplification aggressive enough to collapse a polygon below 4 points (the simplifier is supposed to enforce min points, but a misconfigured maxPoints or a custom code path can bypass that).

Related errors


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