oracle/graal · error · FormatVersionException
Could not deserialize a continuation object.
Error message
Could not deserialize a continuation object.
What it means
Thrown as FormatVersionException by the static bridge ContinuationSerializable.readObjectExternal when the requested type is neither a subtype of Continuation nor of SuspendCapability. This dispatcher is the deserialization entry for the whole 'continuation object' family; it refuses types outside that hierarchy because no reader exists for them.
Source
Thrown at espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationSerializable.java:101
*
* @param type The type of the object to deserialize. Can be either {@link Continuation} or
* {@link SuspendCapability}.
* @param loader The class loader that will be used to deserialize the stack record. If
* {@code null}, the {@link Thread#getContextClassLoader() current thread context
* class loader} will be used.
* @param registerFreshObject A callback to the serialization framework. Intended to be used to
* register the in-construction object, so the framework may handle object graph
* cycles.
*/
@SuppressWarnings("unchecked")
public static <T extends ContinuationSerializable> T readObjectExternal(Class<T> type, ObjectInput in, ClassLoader loader, Consumer<T> registerFreshObject)
throws IOException, ClassNotFoundException {
if (Continuation.class.isAssignableFrom(type)) {
return (T) ContinuationImpl.readObjectExternal(in, loader, (Consumer<Continuation>) registerFreshObject);
} else if (SuspendCapability.class.isAssignableFrom(type)) {
return (T) SuspendCapability.readObjectExternal(in, (Consumer<SuspendCapability>) registerFreshObject);
} else {
throw new FormatVersionException("Could not deserialize a continuation object.");
}
}
// region internals
abstract void writeObjectExternal(ObjectOutput out) throws IOException;
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Only route classes that extend Continuation (ContinuationImpl) or SuspendCapability through this API.
- For your own serializable types, implement readObjectExternal/writeObjectExternal on a ContinuationSerializable subclass instead of calling the static bridge.
- Validate the class before calling: Continuation.class.isAssignableFrom(type) || SuspendCapability.class.isAssignableFrom(type).
- If the type should be a continuation but is not, check that your class extends the public Continuation API class from org.graalvm.continuations, not a look-alike from another package.
Example fix
// before
T obj = ContinuationSerializable.readObjectExternal(type, in, loader, this::register);
// after
if (!Continuation.class.isAssignableFrom(type) && !SuspendCapability.class.isAssignableFrom(type)) {
throw new IllegalArgumentException(type + " is not deserializable by the continuation framework");
}
T obj = ContinuationSerializable.readObjectExternal(type, in, loader, this::register); Defensive patterns
Strategy: type-guard
Type guard
static boolean isContinuationSerializableType(Class<?> t) {
return Continuation.class.isAssignableFrom(t) || SuspendCapability.class.isAssignableFrom(t);
} Prevention
- Route only Continuation/SuspendCapability subtypes through ContinuationSerializable.readObjectExternal.
- For your own types, subclass ContinuationSerializable and implement its hooks instead of using the static bridge.
- In generic frameworks, dispatch on type before calling the bridge.
When it happens
Trigger: Calling ContinuationSerializable.readObjectExternal(MyType.class, in, loader, reg) where MyType does not extend Continuation or SuspendCapability; passing an interface or Class<?> obtained reflectively that looks like a serializable continuation but is not.
Common situations: Generic deserialization frameworks (Kryo/Java serialization bridges, polyglot serializers) that route arbitrary classes through this entry point; copy-pasting a readObjectExternal call from continuation code into a custom serializable class.
Related errors
- You can't resume a continuation while it is being serialized
- You cannot serialize a continuation whilst it's running, as
- This VM does not support continuations.
- Unsupported serialized continuation version: %s\nCurrent sup
- Illegal serialized continuation is in running state.
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/40ea2379c10a4722.
Report an issue: GitHub.