apache/flink · critical · IOException

Unrecognized version: {}

Error message

Unrecognized version: {}

What it means

Thrown by NestedSerializersSnapshotDelegate.readNestedSerializerSnapshots when the version integer read after the magic number does not equal the current VERSION constant (1). This means the serialized nested-snapshots segment was written by a format revision the running Flink version does not understand, or the stream is corrupt and the version field holds garbage.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeutils/NestedSerializersSnapshotDelegate.java:128

        for (TypeSerializerSnapshot<?> snap : nestedSnapshots) {
            TypeSerializerSnapshot.writeVersionedSnapshot(out, snap);
        }
    }

    /** Reads the composite snapshot of all the contained serializers. */
    public static NestedSerializersSnapshotDelegate readNestedSerializerSnapshots(
            DataInputView in, ClassLoader cl) throws IOException {
        final int magicNumber = in.readInt();
        if (magicNumber != MAGIC_NUMBER) {
            throw new IOException(
                    String.format(
                            "Corrupt data, magic number mismatch. Expected %8x, found %8x",
                            MAGIC_NUMBER, magicNumber));
        }

        final int version = in.readInt();
        if (version != VERSION) {
            throw new IOException("Unrecognized version: " + version);
        }

        final int numSnapshots = in.readInt();
        final TypeSerializerSnapshot<?>[] nestedSnapshots =
                new TypeSerializerSnapshot<?>[numSnapshots];

        for (int i = 0; i < numSnapshots; i++) {
            nestedSnapshots[i] = TypeSerializerSnapshot.readVersionedSnapshot(in, cl);
        }

        return new NestedSerializersSnapshotDelegate(nestedSnapshots);
    }

    // ------------------------------------------------------------------------
    //  Utilities
    // ------------------------------------------------------------------------

    private static TypeSerializer<?>[] snapshotsToRestoreSerializers(

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Restore with the Flink version that wrote the checkpoint, then re-save if you need to migrate.
  2. Follow the Flink upgrade path (only restore from compatible versions; check the state compatibility docs for your versions).
  3. If the file is corrupt (not a version issue), re-take the checkpoint from a good state.
  4. Verify there is no accidental double-read of the stream causing misalignment.
Defensive patterns

Strategy: validation

Validate before calling

// Verify Flink version compatibility before restore (documented upgrade path)
// Ensure the writing version and restoring version share NestedSerializersSnapshotDelegate.VERSION

Try / catch

try {
    backend.restore(checkpointPath);
} catch (IOException e) {
    if (e.getMessage().contains("Unrecognized version")) {
        log.error("Checkpoint written by an incompatible Flink version. Restore with the original version first.");
    }
    throw e;
}

Prevention

When it happens

Trigger: Restoring a checkpoint/savepoint written by a newer Flink version that incremented the NestedSerializersSnapshotDelegate VERSION. Reading corrupt data where the version integer is a random value. A custom serialization format that reused this delegate's binary layout with a different version scheme.

Common situations: Upgrading Flink and attempting to restore an old checkpoint whose nested-snapshot format predates the current version (if a legacy read path is missing). Downgrading Flink and reading a checkpoint written by a newer format. File corruption producing a bogus version integer.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/9640efa6b675d95b. Report an issue: GitHub.