{"record":{"id":"bf731d00479ba86e","repo":"apache/iceberg","slug":"unknown-read-version-readversion","errorCode":null,"errorMessage":"Unknown read version: ${readVersion}","messagePattern":"Unknown read version: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/sink/shuffle/SortKeySerializer.java","lineNumber":358,"sourceCode":"      Preconditions.checkState(sortOrder != null, \"Invalid sort order: null\");\n\n      StringUtils.writeString(SchemaParser.toJson(schema), out);\n      StringUtils.writeString(SortOrderParser.toJson(sortOrder), out);\n    }\n\n    @Override\n    public void readSnapshot(int readVersion, DataInputView in, ClassLoader userCodeClassLoader)\n        throws IOException {\n      switch (readVersion) {\n        case 1:\n          read(in);\n          this.version = 1;\n          break;\n        case 2:\n          read(in);\n          break;\n        default:\n          throw new IllegalArgumentException(\"Unknown read version: \" + readVersion);\n      }\n    }\n\n    @Override\n    public TypeSerializerSchemaCompatibility<SortKey> resolveSchemaCompatibility(\n        TypeSerializerSnapshot<SortKey> oldSerializerSnapshot) {\n      if (!(oldSerializerSnapshot instanceof SortKeySerializerSnapshot)) {\n        return TypeSerializerSchemaCompatibility.incompatible();\n      }\n\n      if (oldSerializerSnapshot.getCurrentVersion() == 1 && this.getCurrentVersion() == 2) {\n        return TypeSerializerSchemaCompatibility.compatibleAfterMigration();\n      }\n\n      // Sort order should be identical\n      SortKeySerializerSnapshot oldSnapshot = (SortKeySerializerSnapshot) oldSerializerSnapshot;\n      if (!sortOrder.sameOrder(oldSnapshot.sortOrder)) {\n        return TypeSerializerSchemaCompatibility.incompatible();","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/sink/shuffle/SortKeySerializer.java#L340-L376","documentation":"SortKeySerializer.readSnapshot throws IllegalArgumentException when the on-disk serializer snapshot version (readVersion) is neither 1 nor 2. The snapshot encodes which binary layout was used to write SortKey state; a version outside the known set cannot be resolved, typically meaning the state was written by a newer Iceberg/Flink build than the one reading it.","triggerScenarios":"Restoring a Flink checkpoint/savepoint (via resolveSchemaCompatibility -> readSnapshot, exercised by roundTrip in tests) whose snapshot bytes contain a version tag greater than the reader's supported versions (1 and 2).","commonSituations":"Rolling upgrade rollback: job state written with a newer Iceberg Flink sink version is restored by an older runtime; mixing Iceberg versions across cluster restarts; corrupted or hand-edited savepoint metadata.","solutions":["Run the same or newer Iceberg/Flink version that wrote the checkpoint when restoring state","Downgrade state instead of the runtime: rebuild state from source or a savepoint taken with a compatible writer version","Check the Iceberg version in the job jar versus the cluster classpath for version skew"],"exampleFix":"// before: downgrading iceberg-flink-runtime from 1.20-1.7.x to 1.20-1.5.x while resuming a savepoint\n// after: keep the writer's Iceberg version (or newer) for the restore\n./bin/flink run -c Job job.jar  // with iceberg-flink-runtime >= the version that wrote the savepoint","handlingStrategy":"try-catch","validationCode":"// before restoring, record the writer version used for the savepoint and compare with the runtime's iceberg-flink version\n// (no in-process pre-check API; snapshot version is read during restore)","typeGuard":null,"tryCatchPattern":"try {\n  operator.initializeState(state);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Unknown read version\")) {\n    throw new IllegalStateException(\"Savepoint written by a newer Iceberg version; upgrade the job jar before restoring\", e);\n  }\n  throw e;\n}","preventionTips":["Never restore a savepoint with an older iceberg-flink-runtime than the one that wrote it","Pin the Iceberg version across rolling upgrades/downgrades","Take a fresh savepoint with the target version before rolling back"],"tags":["flink","versioning","savepoint","compatibility"],"backgroundTag":"invalid-enum-value","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"}