{"record":{"id":"f3bfeb23d5f910a8","repo":"apache/iceberg","slug":"failed-to-decode-partition-f3bfeb","errorCode":null,"errorMessage":"Failed to decode partition","messagePattern":"Failed to decode partition","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/operator/StructLikeSerializer.java","lineNumber":121,"sourceCode":"        boolean isNull = dis.readBoolean();\n        if (isNull) {\n          partition.set(i, null);\n        } else {\n          int length = dis.readInt();\n          byte[] bytes = new byte[length];\n          dis.readFully(bytes);\n          Object value = Conversions.fromByteBuffer(fields.get(i).type(), ByteBuffer.wrap(bytes));\n          // Conversions returns CharBuffer for STRING; PartitionData (and the manifest writer)\n          // expects String.\n          if (value instanceof CharSequence cs && !(value instanceof String)) {\n            value = cs.toString();\n          }\n\n          partition.set(i, value);\n        }\n      }\n    } catch (IOException e) {\n      throw new UncheckedIOException(\"Failed to decode partition\", e);\n    }\n\n    return partition;\n  }\n\n  private void writeField(StructLike struct, int pos, Type fieldType) throws IOException {\n    Object value = struct.get(pos, Object.class);\n    if (value == null) {\n      dos.writeBoolean(true);\n      return;\n    }\n\n    dos.writeBoolean(false);\n    ByteBuffer buf = Conversions.toByteBuffer(fieldType, value);\n    dos.writeInt(buf.remaining());\n    dos.write(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());\n  }\n}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/operator/StructLikeSerializer.java#L103-L139","documentation":"StructLikeSerializer.decodePartition reads back an encoded partition byte[] into a mutable StructLike, field by field, using the supplied partition Types.StructType. An IOException while reading (truncated buffer, unexpected end of stream, or a field written with a different type/layout than readField expects) is wrapped in an UncheckedIOException 'Failed to decode partition'.","triggerScenarios":"decodePartition receives bytes not produced by the matching encodePartition call — e.g. empty/truncated byte arrays, bytes encoded with a different partition type, or state restored from a different schema version.","commonSituations":"Partition spec/schema changed between encode and decode (index entries persisted across a schema evolution); corrupted or empty byte arrays read back from RocksDB/state or checkpoint; wrong partitionType argument causing field-type mismatch mid-read.","solutions":["Ensure the byte[] comes from the same serializer/schema version; rebuild the index after partition-spec or schema evolution instead of decoding stale keys.","Validate the byte array is non-empty and the expected length before calling decodePartition.","Pass the same Types.StructType used at encode time (store specId alongside the encoded partition).","Inspect the wrapped cause to identify at which field the read failed and compare against the encoding schema."],"exampleFix":"// before\nStructLike p = StructLikeSerializer.decodePartition(bytes, table.spec().partitionType());\n// stale bytes encoded with an older spec\n\n// after\nif (bytes == null || bytes.length == 0) {\n  throw new IllegalArgumentException(\"No encoded partition stored\");\n}\nStructLike p = StructLikeSerializer.decodePartition(bytes, specTypeAtEncodeTime);","handlingStrategy":"validation","validationCode":"if (bytes == null || bytes.length == 0) {\n  throw new IllegalArgumentException(\"No encoded partition bytes to decode\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  StructLike p = StructLikeSerializer.decodePartition(bytes, partitionType);\n} catch (UncheckedIOException e) {\n  LOG.error(\"Partition decode failed (stale or corrupt bytes): {}\", e.getCause().getMessage());\n  // drop the stale index entry and rebuild it\n}","preventionTips":["Decode only with the same partition type used at encode time (persist specId)","Rebuild the index after schema/partition-spec evolution rather than decoding stale entries","Check byte arrays for emptiness/truncation before decoding"],"tags":["serialization","flink","partition","decoding"],"backgroundTag":"json-decode-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}