{"record":{"id":"1cf90bc5bb806104","repo":"oracle/graal","slug":"an-exception-escaped-the-continuation","errorCode":null,"errorMessage":"An exception escaped the continuation.","messagePattern":"An exception escaped the continuation\\.","errorType":"exception","errorClass":"ContinuationExecutionException","httpStatus":null,"severity":"error","filePath":"espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java","lineNumber":708,"sourceCode":"     */\n    @SuppressWarnings(\"unused\")\n    private void run() {\n        assert state == State.RUNNING : state; // set in #resume()\n        SuspendCapability cap = SuspendCapability.create(this);\n        try {\n            try {\n                entryPoint.start(cap);\n            } catch (Throwable e) {\n                if (!updateState(State.RUNNING, State.FAILED)) {\n                    // force failed state and maybe assert\n                    State badState = forceState(State.FAILED);\n                    if (ASSERTIONS_ENABLED) {\n                        AssertionError assertionError = new AssertionError(badState.toString());\n                        assertionError.addSuppressed(e);\n                        throw assertionError;\n                    }\n                }\n                throw new ContinuationExecutionException(e);\n            }\n            if (!updateState(State.RUNNING, State.COMPLETED)) {\n                // force completed state and maybe assert\n                State badState = forceState(State.COMPLETED);\n                if (ASSERTIONS_ENABLED) {\n                    throw new AssertionError(badState.toString());\n                }\n            }\n        } finally {\n            stackFrameHead = null;\n        }\n    }\n\n    /**\n     * A newly constructed continuation starts in {@link State#NEW}. After the first call to\n     * {@link #resume()} the state will become {@link State#RUNNING} until either the entry point\n     * returns, at which point the state becomes {@link State#COMPLETED}, or until the continuation\n     * suspends, at which point it will be {@link State#SUSPENDED}.","sourceCodeStart":690,"sourceCodeEnd":726,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java#L690-L726","documentation":"This is the message of ContinuationExecutionException, thrown by ContinuationImpl's run entry (startInternal) when entryPoint.start(cap) throws. The library wraps the escaping throwable so callers can distinguish 'the code inside the continuation failed' from 'the continuation machinery failed'; the original exception is the cause. The continuation is also transitioned to State.FAILED before rethrowing.","triggerScenarios":"The ContinuationEntryPoint.start implementation (or anything it calls on the continuation's stack) throws any Throwable while the continuation runs via Continuation.start/enter; the guest code has an unhandled exception at its top frame.","commonSituations":"Business logic inside the continuation throwing a RuntimeException or Error; a suspend-capable task whose entry point does not catch its own exceptions; NPEs or timeouts surfacing from guest code during a resumed continuation.","solutions":["Inspect getCause() of the ContinuationExecutionException — the root cause is always the exception that escaped the entry point; fix that first.","Wrap the body of your ContinuationEntryPoint.start in a try-catch that records the failure, so the continuation completes or fails on its own terms.","Catch ContinuationExecutionException at the call site of Continuation.start to convert it into your application's error type instead of letting it propagate.","Check getState() after the failure — the continuation is FAILED and must be rebuilt, not resumed."],"exampleFix":"// before\nclass Task implements ContinuationEntryPoint {\n    public void start(SuspendCapability cap) {\n        doWork(); // throws, escapes as ContinuationExecutionException\n    }\n}\n\n// after\nclass Task implements ContinuationEntryPoint {\n    public void start(SuspendCapability cap) {\n        try {\n            doWork();\n        } catch (Exception e) {\n            failure = e; // handle inside; nothing escapes\n        }\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { cont.start(entry); } catch (ContinuationExecutionException e) { Throwable root = e.getCause(); /* log root, rebuild continuation: state is FAILED */ }","preventionTips":["Catch your own exceptions inside ContinuationEntryPoint.start so nothing escapes.","Always unwrap getCause() — the wrapper only signals that guest code failed.","After this exception, discard the continuation (state FAILED); do not resume it."],"tags":["continuations","runtime","exception-wrapping","graalvm"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}