{"record":{"id":"e6fa23aa3ab2a501","repo":"elastic/elasticsearch","slug":"expected-a-point-got","errorCode":null,"errorMessage":"Expected a POINT, got [{}]","messagePattern":"Expected a POINT, got \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java","lineNumber":736,"sourceCode":"        if (holes.isEmpty()) {\n            return new Polygon(shell);\n        } else {\n            return new Polygon(shell, Collections.unmodifiableList(holes));\n        }\n    }\n\n    private static MultiPoint parseMultiPoint(ByteBuffer byteBuffer) {\n        final int numPoints = byteBuffer.getInt();\n        if (numPoints == 0) {\n            return MultiPoint.EMPTY;\n        }\n        final List<Point> points = new ArrayList<>(numPoints);\n        for (int i = 0; i < numPoints; i++) {\n            final Geometry geometry = parseGeometry(byteBuffer, false);\n            if (geometry instanceof Point p) {\n                points.add(p);\n            } else {\n                throw new IllegalArgumentException(\"Expected a \" + ShapeType.POINT + \", got [\" + geometry.type() + \"]\");\n            }\n\n        }\n        return new MultiPoint(Collections.unmodifiableList(points));\n    }\n\n    private static MultiLine parseMultiLine(ByteBuffer byteBuffer) {\n        final int numLines = byteBuffer.getInt();\n        if (numLines == 0) {\n            return MultiLine.EMPTY;\n        }\n        final List<Line> lines = new ArrayList<>(numLines);\n        for (int i = 0; i < numLines; i++) {\n            final Geometry geometry = parseGeometry(byteBuffer, false);\n            if (geometry instanceof Line l) {\n                lines.add(l);\n            } else {\n                throw new IllegalArgumentException(\"Expected a \" + ShapeType.LINESTRING + \", got [\" + geometry.type() + \"]\");","sourceCodeStart":718,"sourceCodeEnd":754,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java#L718-L754","documentation":"parseMultiPoint (line 725) reads the declared point count, then for each element calls parseGeometry (line 732) and checks instanceof Point (line 733). If a sub-element is not a Point, it throws IllegalArgumentException at line 736 with the actual type. This guards WKB structural integrity: a MULTIPOINT (type 4/1004) must contain only Point elements.","triggerScenarios":"Calling WellKnownBinary.fromWKB with a MULTIPOINT WKB whose sub-elements encode a non-Point geometry (e.g. a producer wrote Line or Polygon bytes inside a MULTIPOINT wrapper). Typical cause is producer bugs, buffer corruption, or endianness misalignment that makes the sub-element's type code parse as a non-Point.","commonSituations":"Cross-system WKB exchange where the producer serializes MULTIPOINT incorrectly (some libraries allow mixed-type multi-geometries). Truncation/offset errors when slicing buffers. Bit flips in transit/storage. Custom WKB emitters that get the sub-element type code wrong.","solutions":["Validate the producer's WKB output against a known-good reference decoder before exchange.","If you control the producer, ensure MULTIPOINT sub-elements carry type code 1 (or 1001 for Z).","Re-emit the geometry from a trusted source (re-serialize via WellKnownBinary.toWKB) to normalize.","Catch IllegalArgumentException and quarantine the offending record for inspection."],"exampleFix":"// before — corrupt MULTIPOINT WKB\nGeometry g = WellKnownBinary.fromWKB(v, false, corruptBytes); // throws: Expected a POINT, got [LINESTRING]\n\n// after — re-serialize from a trusted source\nMultiPoint mp = new MultiPoint(List.of(new Point(0,0), new Point(1,1)));\nbyte[] clean = WellKnownBinary.toWKB(mp, ByteOrder.LITTLE_ENDIAN);\nGeometry g = WellKnownBinary.fromWKB(v, false, clean);","handlingStrategy":"validation","validationCode":"// Structural integrity of a MULTIPOINT WKB cannot be cheaply pre-validated without parsing.\n// Best practice: re-emit from a trusted source.\nbyte[] normalize(MultiPoint mp) { return WellKnownBinary.toWKB(mp, ByteOrder.LITTLE_ENDIAN); }","typeGuard":"// no useful type guard on raw bytes; validate via round-trip from a trusted producer","tryCatchPattern":"try {\n    return WellKnownBinary.fromWKB(v, false, wkb);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Expected a POINT\")) {\n        // quarantine corrupt MULTIPOINT record for inspection\n    }\n    throw e;\n}","preventionTips":["Re-serialize MULTIPOINT from a trusted geometry object before exchange.","Validate producer output against a reference WKB decoder.","Ensure MULTIPOINT sub-elements carry type code 1 (or 1001 for Z)."],"tags":["geo","wkb","deserialization","multipoint","type-mismatch","corrupt","elasticsearch"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}