{"record":{"id":"8149694110e807de","repo":"apache/iceberg","slug":"invalid-wkb-expected-geometry-type-s-but-found","errorCode":null,"errorMessage":"Invalid WKB: expected geometry type %s but found %s","messagePattern":"Invalid WKB: expected geometry type (.+?) but found (.+?)","errorType":"exception","errorClass":"InvalidWkbException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/GeometryBoundsBuilder.java","lineNumber":170,"sourceCode":"  }\n\n  private void parseGeometryBodyAndUpdateBound(\n      ByteBuffer buffer, int expectedType, int expectedDimension) {\n    long typeCode = Integer.toUnsignedLong(buffer.getInt());\n    int dimensionGroup = (int) (typeCode / DIMENSION_DIVISOR);\n    int geometryType = (int) (typeCode % DIMENSION_DIVISOR);\n    // only the seven OGC types in XY/XYZ/XYM/XYZM are bounded here; other valid OGC types (such as\n    // PolyhedralSurface, TIN, and Triangle) are unsupported and cost the value its bounds\n    checkWkb(\n        geometryType >= TYPE_POINT\n            && geometryType <= TYPE_GEOMETRY_COLLECTION\n            && dimensionGroup <= XYZM_GROUP,\n        \"Invalid or unsupported WKB geometry type: %s\",\n        typeCode);\n    // an element of a multi geometry or collection must match its parent's member type and\n    // dimensions; if/throw so the message is built only when a value is actually rejected\n    if (expectedType != ANY_GEOMETRY && geometryType != expectedType) {\n      throw new InvalidWkbException(\n          \"Invalid WKB: expected geometry type \"\n              + typeName(expectedType)\n              + \" but found \"\n              + typeName(geometryType));\n    }\n    if (expectedDimension != ANY_DIMENSION && dimensionGroup != expectedDimension) {\n      throw new InvalidWkbException(\n          \"Invalid WKB: expected dimensions \"\n              + dimensionName(expectedDimension)\n              + \" but found \"\n              + dimensionName(dimensionGroup));\n    }\n\n    int numDimensions = numDimensions(dimensionGroup);\n\n    // checkWkb above already constrained geometryType to the seven OGC types, so no default arm\n    // is reachable here\n    switch (geometryType) {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/GeometryBoundsBuilder.java#L152-L188","documentation":"When parsing WKB for geometry bounds, a nested element of a multi-geometry or geometry collection must match the parent's declared member type (and the column's expected type). If the parsed geometry type differs from the expected type, the bytes are structurally inconsistent with WKB/Parquet typing rules and InvalidWkbException is thrown. Like all InvalidWkb exceptions in this builder, addValue catches it and suppresses bounds for the file instead of failing the write.","triggerScenarios":"Parsing a geometry whose declared type code (after masking the dimension thousands digit) does not match the expected column type, e.g. a MULTIPOINT value stored in a column whose bounds are built with expectedType=POINT, or a heterogeneous geometry collection where members differ from the parent's type.","commonSituations":"Mixed geometry types written into one column where per-column type tracking says otherwise; hand-crafted or corrupted WKB; writers that emit geometry collections where the schema promises a specific type.","solutions":["Ensure every geometry value in a column matches the column's declared geometry type (e.g. don't mix points and polygons).","Regenerate bounds/data with a conformant writer if types were mixed by an older tool.","Inspect the failing geometry's 4-byte type code to confirm what was actually stored.","If the error is caught internally (missing bounds only), locate the offending file and rewrite its geometry column."],"exampleFix":"// before\n// column declared POINT, but value is a LineString WKB (type 2)\nbuilder.addValue(lineStringWkb);\n// after\nbuilder.addValue(pointWkb); // type code 1 matches expected POINT","handlingStrategy":"validation","validationCode":"static int wkbType(ByteBuffer wkb) {\n  int type = wkb.getInt(wkb.position() + 1); // skip order byte\n  return type % 1000; // strip dimension thousands digit\n}\n// verify wkbType equals the column's expected geometry type before writing","typeGuard":"boolean matchesExpectedType(ByteBuffer wkb, int expectedType) {\n  return wkb != null && wkb.remaining() >= 5 && wkbType(wkb) == expectedType;\n}","tryCatchPattern":null,"preventionTips":["Keep one geometry type per column; enforce at the producer/schema level.","Validate type codes in a write-path test suite.","Reject heterogeneous collections upstream before they reach Iceberg."],"tags":["wkb","geometry","type-mismatch","malformed-input"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}