oracle/graal · error · UnsupportedOperationException

This VM does not support continuations.

Error message

This VM does not support continuations.

What it means

UnsupportedOperationException from the static Continuation.readObjectExternal deserialization entry point when the VM does not support continuations. Just like create/resume, reading a serialized continuation requires Java on Truffle with java.Continuum enabled; on other JVMs the native support the frames depend on is absent.

Source

Thrown at espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java:639

            unlock(currentState);
        }
    }

    /**
     * Deserialize a continuation from the provided {@link ObjectInput}.
     *
     * <p>
     * This method is provided to cooperate with non-jdk serialization frameworks.
     *
     * <p>
     * {@code registerFreshObject} will be called once a fresh continuation has been created, but
     * before it has been fully deserialized. It is intended to be a callback to the serialization
     * framework, so it can register the in-construction continuation so the framework may handle
     * object graph cycles.
     */
    static Continuation readObjectExternal(ObjectInput in, ClassLoader loader, Consumer<Continuation> registerFreshObject) throws IOException, ClassNotFoundException {
        if (!isSupported()) {
            throw new UnsupportedOperationException("This VM does not support continuations.");
        }
        ContinuationImpl continuation = new ContinuationImpl();
        registerFreshObject.accept(continuation);
        continuation.readObjectExternalImpl(in, loader);
        return continuation;
    }

    synchronized void readObjectExternalImpl(ObjectInput in, ClassLoader loader) throws IOException, ClassNotFoundException {
        State currentState = lock();
        if (currentState == State.RUNNING) {
            throw new IllegalContinuationStateException("You cannot serialize a continuation whilst it's running, as this would have unclear semantics. Please suspend first.");
        }
        try {
            // At this point, nothing is initialized
            int header = in.readByte();
            int version = (header >> FORMAT_SHIFT) & FORMAT_MASK;
            if (version != FORMAT_VERSION) {
                throw new FormatVersionException(version, FORMAT_VERSION);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Run all deserializing nodes on Java on Truffle with java.Continuum=true.
  2. Check Continuation.isSupported() before attempting to deserialize continuation payloads.
  3. Tag messages with a continuation marker so non-Truffle consumers can reject them early.
  4. Provide an alternative (data-only) serialization format for non-Truffle consumers.

Example fix

// before
Continuation c = Continuation.readObjectExternal(in, loader, reg);

// after
if (!Continuation.isSupported()) {
    throw new UnsupportedOperationException("Deserializing continuations requires Java on Truffle with java.Continuum=true");
}
Continuation c = Continuation.readObjectExternal(in, loader, reg);
Defensive patterns

Strategy: validation

Validate before calling

if (!Continuation.isSupported()) {
    throw new UnsupportedOperationException("deserializing continuations requires Java on Truffle with java.Continuum=true");
}

Prevention

When it happens

Trigger: Deserializing a continuation payload (via the external serialization hook) on a stock JVM or Truffle JVM without java.Continuum; nodes in a cluster with mixed runtimes pulling continuation messages off a queue.

Common situations: Continuation payloads routed through a message broker consumed by heterogeneous workers; dev machines testing deserialization logic on plain JDKs.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/fb45138cc30dd4fa. Report an issue: GitHub.