elastic/elasticsearch · error · IllegalArgumentException

circle [

Error message

circle [

What it means

Thrown by CircleUtils.createRegularGeoShapePolygon when the input Circle encloses the north pole — i.e. the haversine distance from the circle's center to (lat=90, lon=0) is less than the circle's radius. The n-gon approximation used by this method cannot represent a polygon that contains a pole, so it refuses rather than producing a malformed shape.

Solutions

  1. Reduce the radius so it no longer reaches the pole, or move the center away from the pole.
  2. Confirm radius is in meters (getRadiusMeters) — a unit mismatch is the most frequent cause.
  3. If pole-containing coverage is genuinely required, represent it as a different geometry (e.g. a polygon that explicitly includes the pole) rather than via this n-gon helper.

Example fix

// before
Circle c = new Circle(80, 0, 2_000_000); // 2000 km from lat 80 reaches the pole
Polygon p = CircleUtils.createRegularGeoShapePolygon(c, 64); // throws

// after
Circle c = new Circle(80, 0, 500_000); // smaller radius stays clear of the pole
Polygon p = CircleUtils.createRegularGeoShapePolygon(c, 64);
Defensive patterns

Strategy: validation

Validate before calling

double distToNorthPole = slowHaversin(circle.getLat(), circle.getLon(), 90, 0);
if (distToNorthPole < circle.getRadiusMeters()) {
    throw new IllegalArgumentException("circle reaches north pole; reduce radius or move center");
}
return CircleUtils.createRegularGeoShapePolygon(circle, gons);

Try / catch

try {
    return CircleUtils.createRegularGeoShapePolygon(circle, gons);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("north pole")) {
        // reduce radius to just below the pole distance and retry, or skip
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling `CircleUtils.createRegularGeoShapePolygon(circle, gons)` where `slowHaversin(circle.getLat(), circle.getLon(), 90, 0) < circle.getRadiusMeters()`. Typically a circle centered at high northern latitude with a large radius.

Common situations: User-drawn circles near the poles (e.g. Arctic coverage); radius values in the wrong unit (meters expected, miles or km supplied makes the radius ~1000x too large); circles generated from bounding boxes that happen to enclose the pole.

Related errors


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

Appendix: source

Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/CircleUtils.java:38

    static final int CIRCLE_TO_POLYGON_MINIMUM_NUMBER_OF_SIDES = 4;
    static final int CIRCLE_TO_POLYGON_MAXIMUM_NUMBER_OF_SIDES = 1000;

    private CircleUtils() {}

    /**
     * Makes an n-gon, centered at the provided circle's center, and each vertex approximately
     * {@link Circle#getRadiusMeters()} away from the center.
     *
     * It throws an IllegalArgumentException if the circle contains a pole.
     *
     * This does not split the polygon across the date-line. Relies on org.elasticsearch.index.mapper.GeoShapeIndexer to
     * split prepare polygon for indexing.
     *
     * Adapted from from org.apache.lucene.tests.geo.GeoTestUtil
     * */
    public static Polygon createRegularGeoShapePolygon(Circle circle, int gons) {
        if (slowHaversin(circle.getLat(), circle.getLon(), 90, 0) < circle.getRadiusMeters()) {
            throw new IllegalArgumentException(
                "circle [" + circle.toString() + "] contains the north pole. " + "It cannot be translated to a polygon"
            );
        }
        if (slowHaversin(circle.getLat(), circle.getLon(), -90, 0) < circle.getRadiusMeters()) {
            throw new IllegalArgumentException(
                "circle [" + circle.toString() + "] contains the south pole. " + "It cannot be translated to a polygon"
            );
        }
        double[][] result = new double[2][];
        result[0] = new double[gons + 1];
        result[1] = new double[gons + 1];
        for (int i = 0; i < gons; i++) {
            // make sure we do not start at angle 0 or we have issues at the poles
            double angle = i * (360.0 / gons);
            double x = Math.cos(Math.toRadians(angle));
            double y = Math.sin(Math.toRadians(angle));
            double factor = 2.0;
            double step = 1.0;

View on GitHub (pinned to db6a809a66)