oracle/graal · error · IllegalContinuationStateException
This continuation has failed and must be discarded.
Error message
This continuation has failed and must be discarded.
What it means
IllegalContinuationStateException raised by resume() when the continuation previously failed (state FAILED), e.g. its entry point threw an escaping exception. A failed continuation is tainted and must be discarded; resuming is not possible.
Source
Thrown at espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java:379
clearExclusiveOwner();
}
} else if (updateState(State.SUSPENDED, State.RUNNING)) {
setExclusiveOwner();
try {
// We are ready to resume, make sure the VM has the most up-to-date frames
ensureDematerialized();
assert stackFrameHead == null;
return resume0();
} finally {
clearExclusiveOwner();
}
} else {
// illegal state for resume: neither suspended nor new
switch (state) {
case RUNNING -> throw new IllegalContinuationStateException("You can't resume an already executing continuation.");
case COMPLETED ->
throw new IllegalContinuationStateException("This continuation has already completed successfully.");
case FAILED -> throw new IllegalContinuationStateException("This continuation has failed and must be discarded.");
case LOCKED -> throw new IllegalContinuationStateException("You can't resume a continuation while it is being serialized or deserialized.");
// this is racy so ensure we have a general error message in those case
default -> throw new IllegalContinuationStateException("Only new or suspended continuation can be resumed");
}
}
}
@Override
public synchronized StackTraceElement[] getRecordedFrames() {
State currentState = lock();
try {
ensureDematerialized();
return getRecordedFrames0();
} finally {
unlock(currentState);
}
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Catch ContinuationExecutionException, extract the original cause, and abandon the continuation.
- Check getState()/failure handling before any retry; FAILED is terminal.
- Re-run the workload by creating a new Continuation, not by resuming the failed one.
- Exclude resume() from blanket retry policies.
Example fix
// before
try {
continuation.resume();
} catch (Exception e) {
continuation.resume(); // FAILED -> IllegalContinuationStateException
}
// after
try {
continuation.resume();
} catch (ContinuationExecutionException e) {
log.error("workload failed", e.getCause());
// discard continuation; optionally build a new one and re-run the workload
} Defensive patterns
Strategy: try-catch
Validate before calling
if (continuation.getState() == Continuation.State.FAILED) {
// terminal: discard and optionally rebuild from scratch
} Try / catch
try {
continuation.resume();
} catch (ContinuationExecutionException e) {
log.error("workload failed", e.getCause());
// discard; never resume again
} Prevention
- Exclude resume() from automatic retry policies.
- Treat FAILED as terminal; rebuild the workload in a new continuation.
- Handle ContinuationExecutionException explicitly around resume.
When it happens
Trigger: The entry point threw an exception, the continuation transitioned to FAILED, and code retries with resume(); catch blocks around resume() that swallow the ContinuationExecutionException and then call resume() again.
Common situations: Generic retry-on-exception wrappers (resilience4j-style) applied to resume(); supervisors that attempt to restart 'stuck' continuations.
Related errors
- This continuation has already completed successfully.
- Suspend capabilities can only be used inside a running conti
- You can't resume an already executing continuation.
- You can't resume a continuation while it is being serialized
- Only new or suspended continuation can be resumed
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/594729112268e868.
Report an issue: GitHub.