kestra-io/kestra · error · IllegalArgumentException

No task found to restart execution from!

Error message

No task found to restart execution from!

What it means

The `ExecutionService.taskRunToRestart()` method collects all task runs matching a predicate (e.g., `canBeRestarted()` for restart, or matching a specific taskRunId for replay). It then computes the set with ancestors. If this set is empty — meaning no task run matched the predicate — an `IllegalArgumentException` is thrown. This indicates the execution has no restartable tasks, which can happen when all tasks are already in a non-restartable state or when the task list is empty after filtering.

Source

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

        if (emitEvent) {
            eventPublisher.publishEvent(CrudEvent.create(newExecution));
        }
        return newExecution;
    }

    private Set<String> taskRunToRestart(Execution execution, Predicate<TaskRun> predicate) {
        // Original tasks to be restarted
        Set<String> finalTaskRunToRestart = this
            .taskRunWithAncestors(
                execution,
                execution.getTaskRunList()
                    .stream()
                    .filter(predicate)
                    .toList()
            );

        if (finalTaskRunToRestart.isEmpty()) {
            throw new IllegalArgumentException("No task found to restart execution from!");
        }

        return finalTaskRunToRestart;
    }

    public Execution replay(final Execution execution, Flow flow, @Nullable String taskRunId, @Nullable Integer revision, Optional<String> breakpoints) throws Exception {
        if (taskRunId != null) {
            // The task run may live in a loop sub-execution (possibly nested); find the right execution to operate on
            Execution targetExecution = findExecutionWithTaskRun(execution, taskRunId)
                .map(ExecutionWithTaskRun::execution)
                .orElse(execution);
            return replay(targetExecution, flow, taskRunId, revision, breakpoints, false);
        }
        return replay(execution, flow, taskRunId, revision, breakpoints, false);
    }

    public Execution replay(final Execution execution, Flow flow, @Nullable String taskRunId, @Nullable Integer revision, Optional<String> breakpoints, boolean emitEvent) throws Exception {
        return replay(execution, flow, taskRunId, revision, breakpoints, emitEvent, IdUtils.create());

View on GitHub (pinned to 823fada927)

Solutions

  1. Verify the `taskRunId` exists in the execution before calling replay.
  2. For restart, check that at least one task run is in a restartable state — if the execution was already restarted, it may need a fresh execution instead.
  3. Inspect the execution's task run list and their states to understand which tasks are restartable.
  4. If replaying, use the task run ID from the execution's task run list, not the execution ID.

Example fix

// before
executionService.replay(execution, flow, "nonexistentTaskRunId", null, Optional.empty());
// after
List<TaskRun> taskRuns = execution.getTaskRunList();
if (taskRuns == null || taskRuns.stream().noneMatch(tr -> tr.getId().equals(taskRunId))) {
    throw new IllegalArgumentException("TaskRun " + taskRunId + " not found in execution " + execution.getId());
}
executionService.replay(execution, flow, taskRunId, null, Optional.empty());
Defensive patterns

Strategy: validation

Validate before calling

// Validate taskRunId exists and has restartable tasks before calling restart/replay
List<TaskRun> taskRuns = execution.getTaskRunList();
if (ListUtils.isEmpty(taskRuns)) {
    throw new IllegalArgumentException("Execution has no task runs to restart");
}
// For replay: verify the taskRunId exists
if (taskRunId != null && taskRuns.stream().noneMatch(tr -> tr.getId().equals(taskRunId))) {
    throw new IllegalArgumentException("TaskRun '" + taskRunId + "' not found in execution " + execution.getId());
}
// For restart: verify at least one task run is restartable
boolean anyRestartable = taskRuns.stream().anyMatch(tr -> tr.getState().canBeRestarted());
if (!anyRestartable) {
    throw new IllegalArgumentException("No restartable task runs found in execution " + execution.getId());
}

Try / catch

try {
    Execution restarted = executionService.restart(execution, flow, revision);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("No task found to restart execution from!")) {
        log.warn("No restartable tasks in execution {}. Consider triggering a new execution instead.", execution.getId());
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: Restarting an execution where all task runs have already been restarted (they are in RESTARTED state, which is not restartable again). Replaying from a `taskRunId` that does not exist in the execution. An execution whose task runs are all in states that `canBeRestarted()` returns false for.

Common situations: A user replays from a task run ID that was typed/copied incorrectly. An execution has already been restarted and the user tries to restart it again from the same tasks. The execution has no task runs at all (handled by a separate code path, but edge cases exist).

Related errors


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