apache/flink · critical · IOException
Unsupported version: {}
Error message
Unsupported version: {} What it means
NativeS3RecoverableSerializer.deserialize rejects any serialized form whose version differs from CURRENT_VERSION. The serializer is SimpleVersionedSerializer-based: Flink stores a version number next to the bytes, and this implementation supports only its exact current layout, so mismatched versions are treated as unrecoverable corruption rather than attempted migration.
Source
Thrown at flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/writer/NativeS3RecoverableSerializer.java:109
out.writeInt(part.getPartNumber());
out.writeUTF(part.getETag());
}
String incompleteObject = recoverable.incompleteObjectName();
if (incompleteObject == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeUTF(incompleteObject);
out.writeLong(recoverable.incompleteObjectLength());
}
out.flush();
return outputStream.toByteArray();
}
@Override
public NativeS3Recoverable deserialize(int version, byte[] serialized) throws IOException {
if (version != CURRENT_VERSION) {
throw new IOException("Unsupported version: " + version);
}
ByteArrayInputStream inputStream = new ByteArrayInputStream(serialized);
DataInputStream in = new DataInputStream(inputStream);
String objectName = in.readUTF();
String uploadId = in.readUTF();
long numBytesInParts = in.readLong();
int numParts = in.readInt();
List<PartETag> parts = new ArrayList<>(numParts);
for (int i = 0; i < numParts; i++) {
int partNumber = in.readInt();
String eTag = in.readUTF();
parts.add(new PartETag(partNumber, eTag));
}
boolean hasIncompletePart = in.readBoolean();
String incompleteObjectName = null;
long incompleteObjectLength = -1;
if (hasIncompletePart) {
incompleteObjectName = in.readUTF();View on GitHub (pinned to 2f3c205e92)
Solutions
- Pin one consistent version of the flink-s3-fs-native plugin across the job that wrote the checkpoint and the job restoring it.
- If you must move forward, discard the incompatible checkpoint/savepoint and restart the streaming source from an explicit reset point (resume behavior, not exact state).
- Verify the plugin jar in lib/ matches the Flink distribution version (plugin shading must match the connector build).
- If you control the code, add migration paths in deserialize() for prior versions instead of hard-failing.
Defensive patterns
Strategy: validation
Validate before calling
// before restoring, verify plugin/state provenance int v = NativeS3RecoverableSerializer.INSTANCE.getVersion(); // ensure the checkpoint was written by a job using the same plugin version
Prevention
- Pin one flink-s3-fs-native version across write and restore jobs.
- Discard incompatible checkpoints when changing plugin versions.
- Document serializer format changes in release notes.
When it happens
Trigger: Restoring a checkpoint/savepoint that was written by a different (older or newer) version of flink-s3-fs-native whose NativeS3RecoverableSerializer layout differs; any manual corruption of the serialized bytes' version header.
Common situations: Upgrading or downgrading the flink-s3-fs-native plugin jar without discarding incompatible state; mixing plugin versions between the checkpoint-writing job and the restoring job; loading a savepoint taken with an internal build; stale state from before a serializer format change.
Related errors
- Unrecognized version or corrupt state: {version}
- Unrecognized version or corrupt state: {version}
- Corrupt data: Unexpected magic number %08X
- Unrecognized version or corrupt state: {version}
- Corrupt data, magic number mismatch. Expected %8x, found %8x
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/c2e0b569f5652d3b.
Report an issue: GitHub.