apache/flink · error · IOException
Unrecognized version or corrupt state: {}
Error message
Unrecognized version or corrupt state: {} What it means
Thrown by LocalRecoverableSerializer.deserialize when the supplied version integer does not match any known case in its switch statement (currently only version 1 is recognized). LocalRecoverableSerializer is the SimpleVersionedSerializer that persists LocalFileSystem file-sink recovery metadata (target file, temp file, offset). The version comes from SimpleVersionedSerialization framing, so a mismatch means the bytes were produced by a newer, older, or incompatible serializer implementation.
Source
Thrown at flink-core/src/main/java/org/apache/flink/core/fs/local/LocalRecoverableSerializer.java:72
ByteBuffer bb = ByteBuffer.wrap(targetBytes).order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(MAGIC_NUMBER);
bb.putLong(obj.offset());
bb.putInt(targetFileBytes.length);
bb.putInt(tempFileBytes.length);
bb.put(targetFileBytes);
bb.put(tempFileBytes);
return targetBytes;
}
@Override
public LocalRecoverable deserialize(int version, byte[] serialized) throws IOException {
switch (version) {
case 1:
return deserializeV1(serialized);
default:
throw new IOException("Unrecognized version or corrupt state: " + version);
}
}
private static LocalRecoverable deserializeV1(byte[] serialized) throws IOException {
final ByteBuffer bb = ByteBuffer.wrap(serialized).order(ByteOrder.LITTLE_ENDIAN);
if (bb.getInt() != MAGIC_NUMBER) {
throw new IOException("Corrupt data: Unexpected magic number.");
}
final long offset = bb.getLong();
final byte[] targetFileBytes = new byte[bb.getInt()];
final byte[] tempFileBytes = new byte[bb.getInt()];
bb.get(targetFileBytes);
bb.get(tempFileBytes);
final String targetPath = new String(targetFileBytes, CHARSET);
final String tempPath = new String(tempFileBytes, CHARSET);View on GitHub (pinned to 2f3c205e92)
Solutions
- Check the Flink version that wrote the checkpoint/savepoint against the version restoring it; LocalRecoverableSerializer has only ever had version 1, so a mismatch usually means the bytes are not actually a LocalRecoverable payload.
- Verify the byte array passed to deserialize was produced by SimpleVersionedSerialization.writeVersionAndSerialize and not corrupted in transit or storage.
- If migrating across Flink versions, consult the state compatibility / migration notes for the file sink and re-create the savepoint if the format is incompatible.
- Add a guard that logs the version and byte length before calling deserialize to confirm the payload is well-formed.
Example fix
// before
LocalRecoverable r = LocalRecoverableSerializer.INSTANCE.deserialize(version, bytes);
// after — guard against unknown versions
if (version != LocalRecoverableSerializer.INSTANCE.getVersion()) {
throw new IOException("Unsupported LocalRecoverable version " + version
+ "; expected " + LocalRecoverableSerializer.INSTANCE.getVersion());
}
LocalRecoverable r = LocalRecoverableSerializer.INSTANCE.deserialize(version, bytes); Defensive patterns
Strategy: validation
Validate before calling
if (version != LocalRecoverableSerializer.INSTANCE.getVersion()) {
throw new IOException("Unsupported LocalRecoverable version " + version);
} Try / catch
try {
LocalRecoverable r = LocalRecoverableSerializer.INSTANCE.deserialize(version, bytes);
} catch (IOException e) {
if (e.getMessage().contains("Unrecognized version")) {
// handle version mismatch: log, re-create state, or re-throw
}
throw e;
} Prevention
- Always read recovery metadata with SimpleVersionedSerialization.readVersionAndDeSerialize so version framing is handled consistently.
- Do not mix Flink versions across write and restore of local file-sink recovery state.
- Log the version and byte length before deserializing to aid diagnosis.
When it happens
Trigger: Calling LocalRecoverableSerializer.deserialize(version, bytes) with a version other than 1; data produced by SimpleVersionedSerialization.readVersionAndDeSerialize where the embedded version field does not equal 1; restoring a checkpoint or savepoint whose local file-sink recovery metadata was serialized by a future or alternate serializer version.
Common situations: Restoring a job from a savepoint/checkpoint written by a different Flink version that changed the LocalRecoverable format; corrupted or truncated recovery metadata bytes where the version field reads as garbage; using a custom SimpleVersionedSerializer that delegates to LocalRecoverableSerializer with mismatched version wiring.
Related errors
- Invalid version %d
- Incompatible version: found {}, compatible versions are {}
- Serialized data with version %d cannot be read by serializer
- The bytes are serialized with version %d, while this deseria
- Unrecognized version or corrupt state: {version}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/fc2dc818c7ad3711.
Report an issue: GitHub.