kestra-io/kestra · error · IllegalStateException

Execution '{executionId}' is not paused, can't resume it

Error message

Execution '{executionId}' is not paused, can't resume it

What it means

The `ExecutionService.getExecutionIfPause()` method retrieves an execution and checks whether it is in a paused state (`isPaused()` returns true for PAUSED and some PAUSED-on-breakpoint states). If the execution is not paused, an `IllegalStateException` is thrown. This guard prevents resume operations on executions that are actively running or already terminated.

Source

Thrown at core/src/main/java/io/kestra/core/services/ExecutionService.java:118

    private DispatchQueueInterface<ExecutionCommand> executionCommandQueue;

    @Inject
    private BroadcastQueueInterface<ExecutionKilled> killQueue;

    @Inject
    private AsyncOperationWaiter asyncOperationWaiter;

    @Inject
    private AsyncOperationsConfiguration asyncOperationsConfiguration;

    @Inject
    private Optional<OpenTelemetry> openTelemetry;

    public Execution getExecutionIfPause(final String tenant, final @NotNull String executionId, boolean withACL) {
        Execution execution = getExecution(tenant, executionId, withACL);

        if (!execution.getState().isPaused()) {
            throw new IllegalStateException("Execution '" + executionId + "' is not paused, can't resume it");
        }

        return execution;
    }

    public Execution getExecution(final String tenant, final @NotNull String executionId, boolean withACL) {
        Optional<Execution> maybeExecution = withACL ? executionRepository.findById(tenant, executionId) : executionRepository.findByIdWithoutAcl(tenant, executionId);

        return maybeExecution
            .orElseThrow(() -> new NoSuchElementException("Execution '" + executionId + "' not found."));
    }

    /**
     * Retry set the given taskRun in the created state
     * and return the execution in the running state
     **/
    public Execution retryTask(Execution execution, Flow flow, String taskRunId) throws InternalException {
        TaskRun taskRun = execution.findTaskRunByTaskRunId(taskRunId).withState(State.Type.CREATED);

View on GitHub (pinned to 823fada927)

Solutions

  1. Check the execution's current state before attempting to resume — only PAUSED executions can be resumed.
  2. Refresh the execution status in the UI before clicking Resume.
  3. Handle the `IllegalStateException` gracefully in automated resume scripts (the execution may have been resumed already).
  4. If the execution should be paused but isn't, verify the Pause task or breakpoint configuration.

Example fix

// before
Execution exec = executionService.getExecutionIfPause(tenantId, executionId, true);
// after
Execution exec = executionRepository.findById(tenantId, executionId)
    .orElseThrow(() -> new NoSuchElementException("Execution not found"));
if (!exec.getState().isPaused()) {
    log.info("Execution {} is not paused (state: {}), skipping resume", executionId, exec.getState().getCurrent());
    return;
}
exec = executionService.getExecutionIfPause(tenantId, executionId, true);
Defensive patterns

Strategy: validation

Validate before calling

// Check pause state before calling getExecutionIfPause
Execution execution = executionRepository.findById(tenantId, executionId)
    .orElseThrow(() -> new NoSuchElementException("Execution not found"));
if (!execution.getState().isPaused()) {
    throw new IllegalStateException(
        "Cannot resume execution " + executionId + " in state " + execution.getState().getCurrent());
}
Execution paused = executionService.getExecutionIfPause(tenantId, executionId, withACL);

Type guard

import { State } from './types';

const PAUSED_STATES: Set<State.Type> = new Set(['PAUSED']);

function isResumable(state: State.Type): boolean {
    return PAUSED_STATES.has(state);
}

Try / catch

try {
    Execution exec = executionService.getExecutionIfPause(tenantId, executionId, true);
    // resume logic
} catch (IllegalStateException e) {
    if (e.getMessage().contains("is not paused")) {
        log.info("Execution {} is not paused, no resume needed", executionId);
        return; // idempotent: already resumed or was never paused
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling the resume API (`POST /executions/{id}/resume`) on an execution that is RUNNING, SUCCESS, FAILED, etc. Calling resume on an execution that was already resumed by another user/request. Attempting to resume an execution that was never paused.

Common situations: A user clicks 'Resume' in the UI on an execution that has already been resumed. A race condition: two concurrent resume requests, the second one fails. The execution transitioned past PAUSED between the UI status check and the API call.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/2921b5ff1abd3481. Report an issue: GitHub.