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.
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
- Corrupt data, magic number mismatch. Expected %8x, found %8x
- Corrupt data, magic number mismatch. Expected %8x, found %8x
- Corrupt data: Unexpected magic number %08X
- Corrupt data: Unexpected magic number.
- Failed to Java-Deserialize an AvroSerializer instance. Was…
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/c2e0b569f5652d3b.
Report an issue: GitHub.
Appendix: 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)