apache/flink · critical · IllegalStateException
Could not create a restore serializer for enum {}. Probably
Error message
Could not create a restore serializer for enum {}. Probably because an enum value was removed. What it means
EnumSerializer stores enum constants by name. On restore, EnumSerializerSnapshot.readSnapshot reads each checkpointed enum name and maps it back with Enum.valueOf; if a name no longer exists in the current enum class, it throws IllegalStateException. This guards against silent data corruption because the ordinal/name mapping must resolve every saved value.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeutils/base/EnumSerializer.java:227
out.writeUTF(enumConstant.name());
}
}
@Override
public void readSnapshot(int readVersion, DataInputView in, ClassLoader userCodeClassLoader)
throws IOException {
enumClass = InstantiationUtil.resolveClassByName(in, userCodeClassLoader);
int numEnumConstants = in.readInt();
@SuppressWarnings("unchecked")
T[] previousEnums = (T[]) Array.newInstance(enumClass, numEnumConstants);
for (int i = 0; i < numEnumConstants; i++) {
String enumName = in.readUTF();
try {
previousEnums[i] = Enum.valueOf(enumClass, enumName);
} catch (IllegalArgumentException e) {
throw new IllegalStateException(
"Could not create a restore serializer for enum "
+ enumClass
+ ". Probably because an enum value was removed.");
}
}
this.enums = previousEnums;
}
@Override
public TypeSerializer<T> restoreSerializer() {
checkState(enumClass != null, "Enum class can not be null.");
return new EnumSerializer<>(enumClass, enums);
}
@Override
public TypeSerializerSchemaCompatibility<T> resolveSchemaCompatibility(View on GitHub (pinned to 2f3c205e92)
Solutions
- Add the missing enum constant back (marked @Deprecated) so restore can resolve it, then redeploy.
- If removal is intended, run a state migration: restore on the old code, rewrite/transform the state, take a new savepoint, then deploy the new enum.
- Never delete enum constants that appear in checkpointed state; prefer deprecation to preserve the name mapping.
- If the enum is freshly introduced, discard the incompatible savepoint and start a new job.
- Audit enum usages in keyed/operator state before changing them in a release.
Example fix
// before: enum constant PENDING was removed from the deployed jar
// public enum Status { ACTIVE, INACTIVE } // restore fails: 'PENDING' not found
// after: keep the constant to allow restore
// public enum Status { ACTIVE, INACTIVE, @Deprecated PENDING } Defensive patterns
Strategy: try-catch
Validate before calling
// Before deploy, verify every previously-checkpointed enum name still exists
Set<String> oldNames = Set.of("ACTIVE", "INACTIVE", "PENDING"); // from the old savepoint
Set<String> currentNames = Arrays.stream(Status.class.getEnumConstants()).map(Enum::name).collect(Collectors.toSet());
List<String> removed = oldNames.stream().filter(n -> !currentNames.contains(n)).collect(Collectors.toList());
if (!removed.isEmpty()) {
throw new IllegalStateException("Enum constants removed since last savepoint (restore will fail): " + removed);
} Try / catch
try {
env.fromSavepoint(savepointPath);
} catch (IllegalStateException e) {
if (e.getMessage().contains("restore serializer for enum")) {
log.error("An enum constant used in state was removed; re-add it (deprecated) or run a state migration");
}
throw e;
} Prevention
- Never delete enum constants that participate in checkpointed state; deprecate instead.
- Keep a registry of enums used in keyed/operator state and audit changes before release.
- Run a savepoint restore test in CI for jobs with enum-typed state.
- When refactoring enums, perform a state migration: restore old, rewrite, take new savepoint.
When it happens
Trigger: Restoring from a savepoint/checkpoint after removing or renaming an enum constant that was present when the state was checkpointed; the EnumSerializerSnapshot.restoreSerializer/readSnapshot path cannot find the old constant.
Common situations: Refactoring an enum by deleting a value (e.g., removing a Status.PENDING); renaming enum constants; shrinking an enum used as a keyed state or field type; deploying a new JAR version that dropped an enum member.
Related errors
- Unrecognized version or corrupt state: {version}
- Corrupt data: Unexpected magic number %08X
- Cannot instantiate class.
- Corrupt data: Unexpected magic number.
- Failed to Java-Deserialize an AvroSerializer instance. Was e
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/1fed709ae242dc07.
Report an issue: GitHub.