{"record":{"id":"c03266560ed788ef","repo":"oracle/graal","slug":"unsupported-serialized-continuation-version-s-nc","errorCode":null,"errorMessage":"Unsupported serialized continuation version: %s\\nCurrent supported version: %s","messagePattern":"Unsupported serialized continuation version: (.+?)\\\\nCurrent supported version: (.+?)","errorType":"exception","errorClass":"FormatVersionException","httpStatus":null,"severity":"error","filePath":"espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java","lineNumber":657,"sourceCode":"            throw new UnsupportedOperationException(\"This VM does not support continuations.\");\n        }\n        ContinuationImpl continuation = new ContinuationImpl();\n        registerFreshObject.accept(continuation);\n        continuation.readObjectExternalImpl(in, loader);\n        return continuation;\n    }\n\n    synchronized void readObjectExternalImpl(ObjectInput in, ClassLoader loader) throws IOException, ClassNotFoundException {\n        State currentState = lock();\n        if (currentState == State.RUNNING) {\n            throw new IllegalContinuationStateException(\"You cannot serialize a continuation whilst it's running, as this would have unclear semantics. Please suspend first.\");\n        }\n        try {\n            // At this point, nothing is initialized\n            int header = in.readByte();\n            int version = (header >> FORMAT_SHIFT) & FORMAT_MASK;\n            if (version != FORMAT_VERSION) {\n                throw new FormatVersionException(version, FORMAT_VERSION);\n            }\n\n            currentState = (State) in.readObject();\n            if (currentState == State.RUNNING) {\n                throw new IllegalContinuationStateException(\"Illegal serialized continuation is in running state.\");\n            }\n            entryPoint = (ContinuationEntryPoint) in.readObject();\n\n            if (currentState == State.SUSPENDED) {\n                stackFrameHead = FrameRecordSerializer.forIn(version, in) //\n                                .withLoader(loader == null ? Thread.currentThread().getContextClassLoader() : loader) //\n                                .readRecord();\n            }\n            unlock(currentState);\n        } catch (Throwable e) {\n            // If any error occurs, leave the continuation as incomplete.\n            unlock(State.INCOMPLETE);\n            throw e;","sourceCodeStart":639,"sourceCodeEnd":675,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java#L639-L675","documentation":"Thrown as FormatVersionException while deserializing a continuation: the version number encoded in the stream header (bits FORMAT_SHIFT..FORMAT_MASK of the first byte) does not equal ContinuationImpl.FORMAT_VERSION. The library uses this single version number to gate the whole serialized shape (state enum, entry point, frame records), so a mismatch means the bytes cannot be interpreted safely. It exists to fail fast instead of misparsing an incompatible payload.","triggerScenarios":"Calling Continuation.deserialize (or ContinuationImpl.readObjectExternalImpl) on bytes produced by a different release of org.graalvm.continuations where FORMAT_VERSION differs; manually crafting or truncating the stream so the header byte decodes to a wrong version.","commonSituations":"Continuations persisted to disk or sent over the wire between GraalVM builds (e.g. rolling upgrade from an older GraalVM to a newer one); test fixtures recorded with an older library version; mixing continuation classes from two different GraalVM distributions on one classpath.","solutions":["Re-serialize the continuation with the exact same org.graalvm.continuations version that will deserialize it (pin the GraalVM version on both ends).","If migration is required, resume and re-suspend the continuation under the old runtime, then re-serialize and migrate the new payload.","Catch FormatVersionException and treat the payload as poison: drop it and rebuild the continuation from its logical starting point instead of retrying.","Verify the stream was produced by Continuation.serialize and was not truncated/corrupted in transport (check length, checksum) before blaming the version."],"exampleFix":"// before\nContinuation c = Continuation.deserialize(bytes, loader);\n\n// after\ntry {\n    Continuation c = Continuation.deserialize(bytes, loader);\n} catch (FormatVersionException e) {\n    // payload from an incompatible library version: discard and rebuild\n    log.warn(\"Stale continuation payload (version {}), rebuilding\", e.getMessage());\n    return buildFreshContinuation();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { Continuation c = Continuation.deserialize(bytes, loader); } catch (FormatVersionException e) { /* payload incompatible: quarantine and rebuild, never retry same bytes */ }","preventionTips":["Pin producer and consumer of continuation payloads to the identical GraalVM / org.graalvm.continuations version.","Re-serialize (resume + suspend cycle) persisted continuations as an explicit migration step on every upgrade.","Store the library version alongside the payload and refuse mismatched payloads before calling deserialize."],"tags":["serialization","continuations","version-mismatch","graalvm"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}