{"record":{"id":"694d8af9efa947b8","repo":"elastic/elasticsearch","slug":"empty-circle-cannot-be-represented-in-wkb","errorCode":null,"errorMessage":"Empty CIRCLE cannot be represented in WKB","messagePattern":"Empty CIRCLE cannot be represented in WKB","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java","lineNumber":508,"sourceCode":"            }\n        }\n        WellKnownText.checkZorMAttribute(explicitZ, hasZ);\n        writeInt(out, scratch, hasZ ? 1007 : 7);\n        writeInt(out, scratch, subGeometries.size());\n        for (byte[] subGeom : subGeometries) {\n            out.write(subGeom, 0, subGeom.length);\n        }\n    }\n\n    private static void writeWKBCircle(\n        StreamTokenizer stream,\n        ByteArrayOutputStream out,\n        ByteBuffer scratch,\n        boolean explicitZ,\n        GeometryValidator validator\n    ) throws IOException, ParseException {\n        if (WellKnownText.nextEmptyOrOpen(stream).equals(WellKnownText.EMPTY)) {\n            throw new IllegalArgumentException(\"Empty CIRCLE cannot be represented in WKB\");\n        }\n        double x = WellKnownText.nextNumber(stream);\n        double y = WellKnownText.nextNumber(stream);\n        // WKT circle format: (x y r [z]) — radius comes before optional z\n        double r = WellKnownText.nextNumber(stream);\n        double z = Double.NaN;\n        if (WellKnownText.isNumberNext(stream)) {\n            z = WellKnownText.nextNumber(stream);\n        }\n        WellKnownText.nextCloser(stream);\n        validator.validateCoordinate(x, y, z);\n        boolean hasZ = Double.isNaN(z) == false;\n        WellKnownText.checkZorMAttribute(explicitZ, hasZ);\n        // WKB circle format: type x y [z] r — z comes before radius\n        writeInt(out, scratch, hasZ ? 1017 : 17);\n        writeDouble(out, scratch, x);\n        writeDouble(out, scratch, y);\n        if (hasZ) {","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java#L490-L526","documentation":"writeWKBCircle (line 500) is the WKT-to-WKB direct converter for the CIRCLE type (an ES extension). At line 507 it throws IllegalArgumentException when the token following 'CIRCLE' is 'EMPTY', because the WKB circle encoding (type 17/1017) requires center x, y, radius (and optional z) — none meaningful for an empty circle.","triggerScenarios":"Calling WellKnownBinary.fromWKT(\"CIRCLE EMPTY\", byteOrder, coerce[, validator]). The trigger is the literal WKT token 'CIRCLE' followed by 'EMPTY'.","commonSituations":"Indexing optional-radius features where the source represents absence as 'CIRCLE EMPTY'. Round-tripping data that used WKT's empty-circle syntax into a WKB sink. Ingest pipelines that pass through user-supplied circle WKT without normalizing empties.","solutions":["Detect and skip 'CIRCLE EMPTY' (case-insensitive, trimmed) before fromWKT, treating it as absent data.","Normalize empty circles to a concrete value or to a null/absent document upstream.","If you must preserve emptiness, store WKT rather than WKB, or use a sentinel schema field."],"exampleFix":"// before\nbyte[] wkb = WellKnownBinary.fromWKT(\"CIRCLE EMPTY\", BO, false, v); // throws\n\n// after\nString wkt = wktInput.trim();\nif (wkt.equalsIgnoreCase(\"CIRCLE EMPTY\")) {\n    return null;\n}\nbyte[] wkb = WellKnownBinary.fromWKT(wkt, BO, false, v);","handlingStrategy":"validation","validationCode":"boolean isCircleEmpty(String wkt) {\n    return wkt.trim().equalsIgnoreCase(\"CIRCLE EMPTY\");\n}","typeGuard":"static boolean isEmptyCircleWkt(String wkt) {\n    return wkt.trim().equalsIgnoreCase(\"CIRCLE EMPTY\");\n}","tryCatchPattern":"try {\n    return WellKnownBinary.fromWKT(wkt, bo, coerce, v);\n} catch (IllegalArgumentException e) {\n    if (wkt.trim().equalsIgnoreCase(\"CIRCLE EMPTY\")) return null;\n    throw e;\n}","preventionTips":["Filter 'CIRCLE EMPTY' to null/absent before WKB conversion.","Use WKT (not WKB) if empty circles must be preserved.","Apply a shared empty-WKT filter across POINT/CIRCLE/BBOX."],"tags":["geo","wkt","wkb","circle","empty","elasticsearch"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}