{"record":{"id":"751740debd78a704","repo":"elastic/elasticsearch","slug":"empty-envelope-cannot-be-represented-in-wkb","errorCode":null,"errorMessage":"Empty ENVELOPE cannot be represented in WKB","messagePattern":"Empty ENVELOPE 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":540,"sourceCode":"        // 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) {\n            writeDouble(out, scratch, z);\n        }\n        writeDouble(out, scratch, r);\n    }\n\n    private static void writeWKBBBox(\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 ENVELOPE cannot be represented in WKB\");\n        }\n        // TODO: Add 3D bbox support (consistent with WellKnownText.parseBBox)\n        double minX = WellKnownText.nextNumber(stream);\n        WellKnownText.nextComma(stream);\n        double maxX = WellKnownText.nextNumber(stream);\n        WellKnownText.nextComma(stream);\n        double maxY = WellKnownText.nextNumber(stream);\n        WellKnownText.nextComma(stream);\n        double minY = WellKnownText.nextNumber(stream);\n        WellKnownText.nextCloser(stream);\n        validator.validateBBox(minX, maxX, maxY, minY);\n        validator.validateCoordinate(minX, minY, Double.NaN);\n        validator.validateCoordinate(maxX, maxY, Double.NaN);\n        WellKnownText.checkZorMAttribute(explicitZ, false);\n        writeInt(out, scratch, 18);\n        writeDouble(out, scratch, minX);\n        writeDouble(out, scratch, maxX);\n        writeDouble(out, scratch, maxY);","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java#L522-L558","documentation":"writeWKBBBox (line 532) is the WKT-to-WKB direct converter for the BBOX/ENVELOPE type (ES extension, type 18). At line 539 it throws IllegalArgumentException when the token following 'BBOX' is 'EMPTY', because WKB bbox encoding requires minX, maxX, maxY, minY — an empty envelope has no extents. Note (line 542 TODO) 3D bbox is not yet supported here either.","triggerScenarios":"Calling WellKnownBinary.fromWKT(\"BBOX EMPTY\", byteOrder, coerce[, validator]) or any leading token the dispatcher routes to writeWKBBBox followed by EMPTY.","commonSituations":"Indexing envelope/bbox-shaped documents where the source represents absence as 'BBOX EMPTY'. Caching computed envelopes (some empty) and re-serializing to WKB. Ingest of WKT envelopes that occasionally carry EMPTY.","solutions":["Detect and skip 'BBOX EMPTY' (case-insensitive, trimmed) before fromWKT, treating it as absent.","Normalize empty envelopes to Optional.empty()/null at compute time so they never reach the WKB sink.","Store as WKT (which supports BBOX EMPTY) rather than WKB if emptiness must be preserved."],"exampleFix":"// before\nbyte[] wkb = WellKnownBinary.fromWKT(\"BBOX EMPTY\", BO, false, v); // throws\n\n// after\nString wkt = wktInput.trim();\nif (wkt.equalsIgnoreCase(\"BBOX EMPTY\")) {\n    return null;\n}\nbyte[] wkb = WellKnownBinary.fromWKT(wkt, BO, false, v);","handlingStrategy":"validation","validationCode":"boolean isBboxEmpty(String wkt) {\n    return wkt.trim().equalsIgnoreCase(\"BBOX EMPTY\");\n}","typeGuard":"static boolean isEmptyBboxWkt(String wkt) {\n    return wkt.trim().equalsIgnoreCase(\"BBOX EMPTY\");\n}","tryCatchPattern":"try {\n    return WellKnownBinary.fromWKT(wkt, bo, coerce, v);\n} catch (IllegalArgumentException e) {\n    if (wkt.trim().equalsIgnoreCase(\"BBOX EMPTY\")) return null;\n    throw e;\n}","preventionTips":["Map 'BBOX EMPTY' to Optional.empty()/null at compute time.","Store envelopes as WKT if emptiness must be preserved.","Use a shared empty-WKT filter across POINT/CIRCLE/BBOX."],"tags":["geo","wkt","wkb","bbox","envelope","empty","elasticsearch"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}