apache/dolphinscheduler · error · TaskExecutorRuntimeException

has already started

Error message

${this} has already started

What it means

AbstractTaskExecutor.start is idempotence-guarded by a startFlag; invoking start() on a task executor that has already been started throws TaskExecutorRuntimeException. This prevents double initialization of task context and double publishing of the TaskRunning event.

Solutions

  1. Only call start() once per executor instance; create a fresh executor for a retry
  2. Check isStarted()/startFlag state before calling start()
  3. If restart is needed, build a new task executor instance from the task context

Example fix

// before
if (!taskExecutor.isStarted()) { taskExecutor.start(); }
taskExecutor.start(); // second call throws
// after
if (!taskExecutor.isStarted()) {
    taskExecutor.start();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (taskExecutor.isStarted()) {
    return; // or throw a controlled error at the call site
}
taskExecutor.start();

Type guard

boolean canStart(ITaskExecutor te) {
    return te != null && !te.isStarted();
}

Try / catch

try {
    taskExecutor.start();
} catch (TaskExecutorRuntimeException e) {
    if (!e.getMessage().contains("has already started")) throw e;
    // idempotent no-op: already started
}

Prevention

When it happens

Trigger: Calling start() twice on the same ITaskExecutor instance — e.g. container retry logic re-dispatching an executor that already began, or application code manually calling start after the container already started it.

Common situations: Buggy retry/kill-then-restart logic reusing the same executor object; duplicate event delivery causing a second start; framework code and user code both invoking start.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/628a0ec7c2d0bff5. Report an issue: GitHub.

Appendix: source

Thrown at dolphinscheduler-task-executor/src/main/java/org/apache/dolphinscheduler/task/executor/AbstractTaskExecutor.java:62

    protected final TaskExecutionContext taskExecutionContext;

    protected final TaskExecutorEventBus taskExecutorEventBus;

    public AbstractTaskExecutor(final TaskExecutionContext taskExecutionContext,
                                final TaskExecutorEventBus taskExecutorEventBus) {
        this.taskExecutionContext = taskExecutionContext;
        this.taskExecutorEventBus = taskExecutorEventBus;
        this.latestStateTrackTime = 0;
        this.startFlag = false;
        transitTaskExecutorState(TaskExecutorState.INITIALIZED);
    }

    @SneakyThrows
    @Override
    public void start() {
        if (startFlag) {
            throw new TaskExecutorRuntimeException(this + " has already started");
        }
        startFlag = true;
        TaskInstanceLogHeader.printInitializeTaskContextHeader();
        initializeTaskContext();

        publishTaskRunningEvent();

        TaskInstanceLogHeader.printLoadTaskInstancePluginHeader();
        initializeTaskPlugin();

        TaskInstanceLogHeader.printExecuteTaskHeader();

        if (taskExecutionContext.getDryRun() == Flag.YES.getCode()) {
            log.info("The task: {} is dryRun model, skip the trigger stage.", taskExecutionContext.getTaskName());
            transitTaskExecutorState(TaskExecutorState.SUCCEEDED);
            return;
        }

View on GitHub (pinned to 02eac45a1b)