apache/flink · error · IOException
Unable to serialize default value of type {}.
Error message
Unable to serialize default value of type {}. What it means
During Java serialization of the StateDescriptor (writeObject), Flink serializes the non-null defaultValue using a duplicate of the descriptor's TypeSerializer. If serializer.serialize(defaultValue, outView) throws (e.g., the value type does not match what the serializer expects, or the serializer implementation has a bug), the exception is wrapped in an IOException with the value's simple class name.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/state/StateDescriptor.java:411
out.writeBoolean(false);
} else {
TypeSerializer<T> serializer = serializerAtomicReference.get();
checkNotNull(serializer, "Serializer not initialized.");
// we have a default value
out.writeBoolean(true);
byte[] serializedDefaultValue;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputViewStreamWrapper outView = new DataOutputViewStreamWrapper(baos)) {
TypeSerializer<T> duplicateSerializer = serializer.duplicate();
duplicateSerializer.serialize(defaultValue, outView);
outView.flush();
serializedDefaultValue = baos.toByteArray();
} catch (Exception e) {
throw new IOException(
"Unable to serialize default value of type "
+ defaultValue.getClass().getSimpleName()
+ ".",
e);
}
out.writeInt(serializedDefaultValue.length);
out.write(serializedDefaultValue);
}
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
// read the non-transient fields
in.defaultReadObject();
// read the default value field
boolean hasDefaultValue = in.readBoolean();
if (hasDefaultValue) {View on GitHub (pinned to 2f3c205e92)
Solutions
- Ensure defaultValue's runtime type is exactly the type the descriptor's serializer handles — do not pass a subclass instance as the default.
- Test the serializer round-trip on the default value in isolation (serialize/deserialize) before constructing the descriptor.
- If using a custom TypeSerializer, verify serialize/deserialize are symmetric and handle the default value.
- Avoid setting a default value of a type that the serializer cannot represent; pass null instead and handle missing-state logic in the function.
Example fix
// before
new ValueStateDescriptor<>("n", MyPojo.class, new MyPojoSubclass()); // type mismatch
// after
new ValueStateDescriptor<>("n", MyPojo.class, new MyPojo()); Defensive patterns
Strategy: type-guard
Validate before calling
// Verify the default value type matches the descriptor's type before assigning
T defaultValue = ...;
if (!descriptorTypeClass.isInstance(defaultValue)) {
throw new IllegalArgumentException("Default value type mismatch");
}
// Round-trip test the serializer on the default value
TypeSerializer<T> ser = descriptor.getTypeInformation().createSerializer(cfg);
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
ser.serialize(defaultValue, new DataOutputViewStreamWrapper(out));
T copy = ser.deserialize(new DataInputViewStreamWrapper(
new ByteArrayInputStream(out.toByteArray())));
} Type guard
// Ensure defaultValue is exactly the serializer's type
Class<?> t = descriptor.getTypeInformation().getTypeClass();
if (!t.isInstance(defaultValue)) {
throw new ClassCastException(defaultValue + " is not a " + t);
} Try / catch
// Serialization happens during job graph distribution; catch in tests, not in prod.
try {
env.execute(); // triggers descriptor serialization
} catch (Exception e) {
if (e.getCause() instanceof IOException
&& e.getMessage().contains("Unable to serialize default value")) {
// fix the default value type and rebuild
}
} Prevention
- Never pass a subclass instance as a default value when the serializer targets the superclass.
- Add a serialization round-trip test for every descriptor that carries a non-null default.
- Keep the default value's type equal to the descriptor's declared type.
When it happens
Trigger: The defaultValue was set with an instance whose runtime type differs from the serializer's T (e.g., assigning a subclass the serializer cannot handle); a custom TypeSerializer that fails on a particular value; serializing a descriptor whose serializer and default value were configured inconsistently.
Common situations: Distributing the job graph (Java serialization of descriptors to TaskManagers); checkpointing the descriptor; a default value set via a builder that bypasses type checks; upgrading a serializer snapshot while the in-memory default value is stale.
Related errors
- Failed to serialize value '{value}'
- Serializer not yet initialized.
- Unable to deserialize default value.
- Could not serialize serializer into the configuration.
- Could not duplicate SimpleVersionedSerializer.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/751a7360a833f13c.
Report an issue: GitHub.