kestra-io/kestra · error · IllegalStateException
Execution must be terminated or paused and not killed to be
Error message
Execution must be terminated or paused and not killed to be restarted, current state is '{execution.getState().getCurrent()}' ! What it means
The `ExecutionService.restart()` method checks `execution.getState().canBeRestarted()` before proceeding. Only executions in a terminal state (SUCCESS, FAILED, WARNING, etc.) or PAUSED state — and not KILLED — can be restarted. If the execution is still RUNNING, CREATED, QUEUED, or has been KILLED, an `IllegalStateException` is thrown. Restarting re-runs the execution from a specific task.
Source
Thrown at core/src/main/java/io/kestra/core/services/ExecutionService.java:283
if (createCommand.variables() != null) {
newExecution = newExecution.withVariables(createCommand.variables());
}
/*
* if (emitEvent) {
* eventPublisher.publishEvent(CrudEvent.create(newExecution));
* }
*/
return newExecution;
}
public Execution restart(final Execution execution, Flow flow, @Nullable Integer revision) throws Exception {
return restart(execution, flow, revision, false);
}
public Execution restart(final Execution execution, Flow flow, @Nullable Integer revision, boolean emitEvent) throws Exception {
if (!execution.getState().canBeRestarted()) {
throw new IllegalStateException(
"Execution must be terminated or paused and not killed to be restarted, " +
"current state is '" + execution.getState().getCurrent() + "' !"
);
}
final String newExecutionId = revision != null ? IdUtils.create() : null;
// When an execution has no task runs (e.g., failed due to concurrency limit exceeded
// before any task ran), restart it as a fresh child execution with an empty task-run list.
if (ListUtils.isEmpty(execution.getTaskRunList())) {
List<Label> newLabels = new ArrayList<>(ListUtils.emptyOnNull(execution.getLabels()));
if (!newLabels.contains(new Label(Label.RESTARTED, "true"))) {
newLabels.add(new Label(Label.RESTARTED, "true"));
}
Execution newExecution = execution
.childExecution(newExecutionId, Collections.emptyList(), execution.withState(State.Type.RESTARTED).getState())
.withMetadata(execution.getMetadata().nextAttempt())
.withLabels(newLabels);View on GitHub (pinned to 823fada927)
Solutions
- Wait for the execution to reach a terminal state (SUCCESS, FAILED, WARNING) before restarting.
- Killed executions cannot be restarted — trigger a new execution instead.
- Refresh the execution status in the UI before clicking Restart.
- For PAUSED executions, restart is allowed but should be used intentionally (it resumes from the restart point).
Example fix
# before: restart a running execution
POST /api/v1/executions/{runningExecutionId}/restart
# after: wait for terminal state first
# 1. Check execution state
GET /api/v1/executions/{executionId}
# 2. Only restart when state is FAILED, SUCCESS, WARNING, or PAUSED
POST /api/v1/executions/{executionId}/restart Defensive patterns
Strategy: validation
Validate before calling
// Check restartability before calling restart
Execution execution = executionRepository.findById(tenantId, executionId)
.orElseThrow(() -> new NoSuchElementException("Execution not found"));
if (!execution.getState().canBeRestarted()) {
throw new IllegalStateException(
"Cannot restart execution in state " + execution.getState().getCurrent()
+ ". Must be terminated or paused, and not killed.");
}
Execution restarted = executionService.restart(execution, flow, revision); Type guard
const TERMINAL_STATES: Set<string> = new Set(['SUCCESS', 'FAILED', 'WARNING', 'PAUSED', 'CANCELLED']);
function canBeRestarted(state: string): boolean {
return TERMINAL_STATES.has(state) && state !== 'KILLED';
} Try / catch
try {
Execution restarted = executionService.restart(execution, flow, revision);
} catch (IllegalStateException e) {
if (e.getMessage().contains("must be terminated or paused")) {
log.warn("Cannot restart execution {} in state {}: {}",
execution.getId(), execution.getState().getCurrent(), e.getMessage());
// suggest: wait for terminal state, or trigger a new execution if killed
throw e;
}
throw e;
} Prevention
- Verify the execution is in a terminal or paused state before calling restart.
- Killed executions cannot be restarted — trigger a new execution instead.
- Refresh execution status in the UI before clicking Restart.
- Document that RUNNING, CREATED, and QUEUED executions cannot be restarted.
When it happens
Trigger: Calling `POST /executions/{id}/restart` on an execution that is currently RUNNING. Restarting an execution that was KILLED (killed executions cannot be restarted). Restarting an execution that is in a non-terminal, non-paused state like CREATED or QUEUED.
Common situations: A user attempts to restart an execution that is still in progress. A flow was killed by the user or system and the user tries to restart it. The execution state changed between the UI display and the API call.
Related errors
- Only QUEUED execution can be unqueued
- Invalid target state: {state}. Valid states are: {VALID_TARG
- Execution '{executionId}' is not paused, can't resume it
- No task found to restart execution from!
- Both `namespace` and `flowId` must be set when `executionId`
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/74cf222ccb8e3486.
Report an issue: GitHub.