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
- Raise maxPoints so the simplifier cannot collapse the ring below 4 vertices.
- Validate the source polygon has >= 4 vertices before simplifying; reject or pass through degenerate inputs.
- 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
- Never set maxPoints below 4 for a PolygonSimplifier.
- Reject source polygons with fewer than 4 vertices at ingestion.
- If simplification collapses rings below 4, raise maxPoints or fall back to the original geometry.
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
- LinearRing cannot have first and last points differ:
- No points have been consumed
- Unsupported geometry type:
- Unknown simplification error calculator:
- circle [
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/3cbce3027d0ef84e.
Report an issue: GitHub.