elastic/elasticsearch · error · UnsupportedOperationException
Circle is not supported
Error message
Circle is not supported
What it means
SpatialEnvelopeVisitor computes the bounding box (envelope/MBR) of a Geometry by walking its points. Its visit(Circle) override unconditionally throws UnsupportedOperationException because converting a circle's radius (in meters) into x/y extents requires a Coordinate Reference System, which the visitor does not carry. The TODO at line 320 makes this an explicit, known limitation rather than a bug. Until CRS-aware circle expansion is implemented, no Circle — empty or not — can pass through this visitor.
Source
Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/SpatialEnvelopeVisitor.java:321
}
private static Rectangle maybeWrap(double top, double bottom, double negLeft, double negRight, double posLeft, double posRight) {
double unwrappedWidth = posRight - negLeft;
double wrappedWidth = 360 + negRight - posLeft;
return unwrappedWidth <= wrappedWidth
? new Rectangle(negLeft, posRight, top, bottom)
: new Rectangle(posLeft, negRight, top, bottom);
}
}
private boolean isValid() {
return pointVisitor.isValid();
}
@Override
public Boolean visit(Circle circle) throws RuntimeException {
// TODO: Support circle, if given CRS (needed for radius to x/y coordinate transformation)
throw new UnsupportedOperationException("Circle is not supported");
}
@Override
public Boolean visit(GeometryCollection<?> collection) throws RuntimeException {
collection.forEach(geometry -> geometry.visit(this));
return isValid();
}
@Override
public Boolean visit(Line line) throws RuntimeException {
for (int i = 0; i < line.length(); i++) {
pointVisitor.visitPoint(line.getX(i), line.getY(i));
}
return isValid();
}
@Override
public Boolean visit(LinearRing ring) throws RuntimeException {View on GitHub (pinned to db6a809a66)
Solutions
- Filter out or reject Circle geometries before calling the visitor: branch on geometry instanceof Circle (or check geometry.type() == ShapeType.CIRCLE) and skip envelope computation for those documents.
- If you need an envelope for a circle, expand the circle into a Polygon approximation (a bounded number of points around the circumference using the known CRS) before invoking the visitor.
- For GeometryCollection inputs, pre-flatten and drop any Circle children (or recurse manually skipping Circle) so the visitor's collection.forEach at line 326 never reaches visit(Circle).
- Wrap the call in try/catch(UnsupportedOperationException) only as a last resort — this error is deterministic, not transient, so prevention is preferable.
Example fix
// before
Optional<Rectangle> bbox = SpatialEnvelopeVisitor.visitGeo(geometry, WrapLongitude.WRAP);
// after
if (geometry instanceof Circle || containsCircle(geometry)) {
return Optional.empty(); // circles unsupported by envelope visitor
}
Optional<Rectangle> bbox = SpatialEnvelopeVisitor.visitGeo(geometry, WrapLongitude.WRAP); Defensive patterns
Strategy: type-guard
Validate before calling
boolean isEnvelopeSupported(Geometry g) {
if (g instanceof Circle) return false;
if (g instanceof GeometryCollection<?> c) {
return c.stream().allMatch(isEnvelopeSupported::apply); // recurse
}
return true;
} Type guard
static boolean isCircleOrContainsCircle(Geometry g) {
if (g instanceof Circle) return true;
if (g instanceof GeometryCollection<?> c) {
for (Geometry child : c) if (isCircleOrContainsCircle(child)) return true;
}
return false;
} Try / catch
try {
Optional<Rectangle> bbox = SpatialEnvelopeVisitor.visitGeo(geometry, WrapLongitude.WRAP);
} catch (UnsupportedOperationException e) {
// circle encountered — skip envelope for this document
logger.warn("skipping envelope: circle unsupported", e);
} Prevention
- Branch on geometry type before envelope computation; treat Circle as unsupported.
- When indexing circles, also store a precomputed bounding Polygon so query paths never need envelope-of-circle.
- Validate incoming shapes at the API boundary and reject or transform Circle before they reach visitor code.
When it happens
Trigger: Calling SpatialEnvelopeVisitor.visitCartesian(circle), SpatialEnvelopeVisitor.visitGeo(circle, wrap), or geometry.visit(new SpatialEnvelopeVisitor(...)) where geometry is or contains (via GeometryCollection recursion at line 326) a Circle. Note that the collection visit forEach at line 326 will recurse into a Circle child and re-trigger this throw.
Common situations: Indexing geo_shape documents that use circle geometry and then running a query/aggregation that derives an envelope (e.g. for tile/bbox-based filtering, sorting, or _select_shape). Passing user-supplied or third-party GeoJSON/WKT that was parsed into a Circle directly to any code path that calls SpatialEnvelopeVisitor. Migrating data that previously stored circles into a query path that previously only handled polygons.
Related errors
- found Z value [
- Empty CIRCLE cannot be represented in WKB
- Unknown geometry type: {}
- When specifying 'Z' or 'M', coordinates must include three v
- maximum nested depth of 1000 exceeded
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/cce77b2141335584.
Report an issue: GitHub.