{"record":{"id":"54b0de920fc714eb","repo":"kestra-io/kestra","slug":"the-execution-is-not-paused","errorCode":null,"errorMessage":"The execution is not paused","messagePattern":"The execution is not paused","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/services/ExecutionService.java","lineNumber":890,"sourceCode":"     *\n     * @param execution the execution to resume\n     * @param newState should be RUNNING or KILLING, other states may lead to undefined behavior\n     * @param flow the flow of the execution\n     * @param inputs the onResume inputs\n     * @return the execution in the new state.\n     * @throws Exception if the state of the execution cannot be updated\n     */\n    public Execution resume(final Execution execution, FlowInterface flow, State.Type newState, @Nullable Map<String, Object> inputs, @Nullable Pause.Resumed resumed) throws Exception {\n        var pausedTaskRun = execution\n            .findFirstByState(State.Type.PAUSED);\n\n        Execution unpausedExecution;\n        if (pausedTaskRun.isPresent()) {\n            unpausedExecution = this.markAs(execution, flow, pausedTaskRun.get().getId(), newState, inputs, resumed);\n        } else {\n            // we are in a manual execution pause, not triggered by the Pause task, so we just switch the execution to the new state.\n            if (!execution.getState().isPaused()) {\n                throw new IllegalArgumentException(\"The execution is not paused\");\n            }\n            unpausedExecution = execution.withState(newState);\n        }\n\n        this.eventPublisher.publishEvent(CrudEvent.of(execution, unpausedExecution));\n        return unpausedExecution;\n    }\n\n    /**\n     * Pause a running execution.\n     * The execution must be running or this call will throw an IllegalArgumentException.\n     *\n     * @param execution the execution to resume\n     * @return the execution in the new state.\n     * @throws Exception if the state of the execution cannot be updated\n     */\n    public Execution pause(final Execution execution) throws Exception {\n        if (!execution.getState().isRunning()) {","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/services/ExecutionService.java#L872-L908","documentation":"ExecutionService.resume (the inputs-bearing overload at line 880) only works on a paused execution. It first looks for a task run in State.Type.PAUSED; if none exists it falls back to checking the execution-level state via State.isPaused(). When neither condition holds, it throws this IllegalArgumentException, because resuming a non-paused execution has no defined semantic — the execution is either already running or already terminated. The thrown exception bubbles up from resume as a checked throws Exception on the method signature.","triggerScenarios":"Calling resume() on an execution that has no PAUSED task run and whose State.Type is not PAUSED — i.e. the execution is RUNNING, terminated (SUCCESS/FAILED/etc.), KILLING, QUEUED, RETRYING, BREAKPOINT, or CREATED. Entry points: the resume API endpoint, the UI 'Resume' button, or a direct call after a Pause task has already auto-resumed (e.g. its timeout fired and the execution moved on).","commonSituations":"Double-clicking / double-submitting resume (first call unpauses, second hits a no-longer-paused execution); a Pause task configured with a timeout that has already elapsed; race between a manual resume and the scheduler/auto-resume; resuming an execution that was never paused by a Pause task and was never manually paused via the pause API.","solutions":["Before calling resume, fetch the fresh execution and verify execution.findFirstByState(State.Type.PAUSED).isPresent() || execution.getState().isPaused(); otherwise treat it as a no-op or return a 409.","Make the resume endpoint idempotent at the controller/service boundary: if the execution is not paused, return the current execution rather than throwing, so duplicate UI submissions are harmless.","For UI-triggered resumes, disable the Resume button unless the execution state is PAUSED, and re-fetch the execution immediately before the call.","If a Pause task timed out, do not resume — inspect the execution to confirm whether it already transitioned, and surface that to the user."],"exampleFix":"// before\nexecutionService.resume(execution, flow, State.Type.RUNNING, inputs, resumed);\n\n// after\nboolean hasPausedTaskRun = execution.findFirstByState(State.Type.PAUSED).isPresent();\nboolean isExecutionPaused = execution.getState().isPaused();\nif (!hasPausedTaskRun && !isExecutionPaused) {\n    return execution; // already resumed / not paused — nothing to do\n}\nexecutionService.resume(execution, flow, State.Type.RUNNING, inputs, resumed);","handlingStrategy":"validation","validationCode":"import io.kestra.core.models.executions.Execution;\nimport io.kestra.core.models.flows.State;\n\nExecution fresh = executionRepository.findById(tenantId, executionId).orElseThrow();\nboolean paused = fresh.findFirstByState(State.Type.PAUSED).isPresent()\n    || fresh.getState().isPaused();\nif (!paused) {\n    // already resumed, or never paused — no-op\n    return fresh;\n}\nreturn executionService.resume(fresh, flow, State.Type.RUNNING, inputs, resumed);","typeGuard":"// Java guard helper — narrow before calling resume.\npublic static boolean isResumable(Execution execution) {\n    if (execution == null) return false;\n    return execution.findFirstByState(State.Type.PAUSED).isPresent()\n        || execution.getState().isPaused();\n}","tryCatchPattern":"try {\n    executionService.resume(execution, flow, State.Type.RUNNING, inputs, resumed);\n} catch (IllegalArgumentException e) {\n    if (\"The execution is not paused\".equals(e.getMessage())) {\n        // idempotent no-op: execution already moved on; return current state\n        return execution;\n    }\n    throw e;\n}","preventionTips":["Make the resume entry point idempotent: a second resume of an already-resumed execution is a no-op, not an error.","Re-fetch the execution state right before resume to defeat the double-submit / scheduler race.","Disable the UI Resume action unless the execution is in the PAUSED state.","When a Pause task has a timeout, document that auto-resume can win the race — clients should expect 'not paused' and treat it as success."],"tags":["execution","pause","resume","state-machine","kestra-core"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}