{"record":{"id":"704423fbdb354171","repo":"oracle/graal","slug":"suspend-capabilities-can-only-be-used-inside-a-run","errorCode":null,"errorMessage":"Suspend capabilities can only be used inside a running continuation.","messagePattern":"Suspend capabilities can only be used inside a running continuation\\.","errorType":"exception","errorClass":"IllegalContinuationStateException","httpStatus":null,"severity":"error","filePath":"espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java","lineNumber":476,"sourceCode":"                if (j < record.pointers.length - 1) {\n                    sb.append(\", \");\n                }\n            }\n            sb.append(\"\\n\");\n        }\n        return sb.toString();\n    }\n\n    /**\n     * Called from {@link SuspendCapability#suspend()}. Suspends this continuation. If successful,\n     * execution resumes back at {@link #resume()}.\n     */\n    void trySuspend() {\n        if (exclusiveOwner != Thread.currentThread()) {\n            throw new IllegalContinuationStateException(\"Suspend capabilities can only be used inside a continuation.\");\n        }\n        if (!updateState(State.RUNNING, State.SUSPENDED)) {\n            throw new IllegalContinuationStateException(\"Suspend capabilities can only be used inside a running continuation.\");\n        }\n        try {\n            suspend();\n        } catch (IllegalContinuationStateException e) {\n            if (!updateState(State.SUSPENDED, State.RUNNING)) {\n                // force failed state and maybe assert\n                State badState = forceState(State.RUNNING);\n                if (ASSERTIONS_ENABLED) {\n                    AssertionError assertionError = new AssertionError(badState.toString());\n                    assertionError.addSuppressed(e);\n                    throw assertionError;\n                }\n            }\n            throw e;\n        }\n        // set in #resume()\n        assert state == State.RUNNING : state;\n    }","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java#L458-L494","documentation":"IllegalContinuationStateException from trySuspend when the calling thread owns the continuation but its state is not RUNNING, so the RUNNING->SUSPENDED CAS fails. The continuation already moved (e.g. suspended by another path, completed, or is mid-transition), so a second suspend is illegal.","triggerScenarios":"Calling SuspendCapability.suspend() twice; suspending from a re-entrant callback after the state already changed to SUSPENDED; suspend racing with a state transition driven by serialization or failure handling.","commonSituations":"Retrying suspend in a catch block after the first attempt partially progressed; multiple suspension points triggered by the same event; nested callbacks each attempting to suspend.","solutions":["Call suspend() at most once per activation; after resume() returns from a suspend, do not suspend again until re-resumed.","Structure the entry point so only one place performs the suspension decision.","On this exception, check getState() and unwind instead of retrying.","Keep suspend logic on the continuation thread only (also avoids error 595)."],"exampleFix":"// before\ntry {\n    capability.suspend();\n} catch (IllegalContinuationStateException e) {\n    capability.suspend(); // double-suspend -> this error again\n}\n\n// after\nif (continuation.getState() == Continuation.State.RUNNING) {\n    capability.suspend();\n} else {\n    return; // already suspended/completed; unwind","handlingStrategy":"validation","validationCode":"if (continuation.getState() == Continuation.State.RUNNING) {\n    capability.suspend();\n} else {\n    // already suspended/completed; return instead of suspending again\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Suspend at most once per activation.","Consolidate the suspend decision to one place in the entry point.","On IllegalContinuationStateException from suspend, check state and unwind."],"tags":["continuations","illegal-state","lifecycle","graalvm","truffle"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}