{"record":{"id":"1a4afe41bf9f77d4","repo":"elastic/elasticsearch","slug":"expected-a-linestring-got","errorCode":null,"errorMessage":"Expected a LINESTRING, got [{}]","messagePattern":"Expected a LINESTRING, got \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java","lineNumber":754,"sourceCode":"                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() + \"]\");\n            }\n        }\n        return new MultiLine(Collections.unmodifiableList(lines));\n    }\n\n    private static MultiPolygon parseMultiPolygon(ByteBuffer byteBuffer, boolean coerce) {\n        final int numPolygons = byteBuffer.getInt();\n        if (numPolygons == 0) {\n            return MultiPolygon.EMPTY;\n        }\n        final List<Polygon> polygons = new ArrayList<>(numPolygons);\n        for (int i = 0; i < numPolygons; i++) {\n            final Geometry geometry = parseGeometry(byteBuffer, coerce);\n            if (geometry instanceof Polygon p) {\n                polygons.add(p);\n            } else {\n                throw new IllegalArgumentException(\"Expected a \" + ShapeType.POLYGON + \", got [\" + geometry.type() + \"]\");\n            }","sourceCodeStart":736,"sourceCodeEnd":772,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownBinary.java#L736-L772","documentation":"parseMultiLine (line 743) reads the declared line count, then for each element calls parseGeometry (line 750) and checks instanceof Line (line 751). A non-Line sub-element triggers IllegalArgumentException at line 754. WKB MULTILINESTRING (type 5/1005) must contain only LineString elements.","triggerScenarios":"Calling WellKnownBinary.fromWKB with a MULTILINESTRING WKB whose sub-elements are not LineString-encoded (e.g. Point or Polygon bytes inside the wrapper). Producer bugs, buffer corruption, or endianness misalignment are the usual causes.","commonSituations":"Interoperability with WKB emitters that allow mixed-type multi-geometries. Truncated/misaligned buffers where a coordinate is misread as a type code. Custom serializers that emit the wrong sub-element type code.","solutions":["Validate producer output against a reference decoder before exchange.","Ensure MULTILINESTRING sub-elements carry type code 2 (or 1002 for Z) if you control the producer.","Re-serialize from a trusted geometry object via WellKnownBinary.toWKB to normalize.","Catch and quarantine corrupt records for offline inspection."],"exampleFix":"// before\nGeometry g = WellKnownBinary.fromWKB(v, false, corruptBytes); // throws: Expected a LINESTRING, got [POINT]\n\n// after — re-emit from trusted source\nMultiLine ml = new MultiLine(List.of(new Line(new double[]{0,1}, new double[]{0,1})));\nbyte[] clean = WellKnownBinary.toWKB(ml, ByteOrder.LITTLE_ENDIAN);\nGeometry g = WellKnownBinary.fromWKB(v, false, clean);","handlingStrategy":"validation","validationCode":"// No cheap structural pre-check; normalize by re-emitting from trusted source.\nbyte[] normalize(MultiLine ml) { return WellKnownBinary.toWKB(ml, ByteOrder.LITTLE_ENDIAN); }","typeGuard":"// no useful type guard on raw bytes; validate via round-trip","tryCatchPattern":"try {\n    return WellKnownBinary.fromWKB(v, false, wkb);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Expected a LINESTRING\")) {\n        // quarantine corrupt MULTILINESTRING record\n    }\n    throw e;\n}","preventionTips":["Re-serialize MULTILINESTRING from a trusted geometry object before exchange.","Validate producer output against a reference decoder.","Ensure MULTILINESTRING sub-elements carry type code 2 (or 1002 for Z)."],"tags":["geo","wkb","deserialization","multilinestring","type-mismatch","corrupt","elasticsearch"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}