{"record":{"id":"628a0ec7c2d0bff5","repo":"apache/dolphinscheduler","slug":"this-has-already-started","errorCode":null,"errorMessage":"${this} has already started","messagePattern":"(.+?) has already started","errorType":"exception","errorClass":"TaskExecutorRuntimeException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-task-executor/src/main/java/org/apache/dolphinscheduler/task/executor/AbstractTaskExecutor.java","lineNumber":62,"sourceCode":"\n    protected final TaskExecutionContext taskExecutionContext;\n\n    protected final TaskExecutorEventBus taskExecutorEventBus;\n\n    public AbstractTaskExecutor(final TaskExecutionContext taskExecutionContext,\n                                final TaskExecutorEventBus taskExecutorEventBus) {\n        this.taskExecutionContext = taskExecutionContext;\n        this.taskExecutorEventBus = taskExecutorEventBus;\n        this.latestStateTrackTime = 0;\n        this.startFlag = false;\n        transitTaskExecutorState(TaskExecutorState.INITIALIZED);\n    }\n\n    @SneakyThrows\n    @Override\n    public void start() {\n        if (startFlag) {\n            throw new TaskExecutorRuntimeException(this + \" has already started\");\n        }\n        startFlag = true;\n        TaskInstanceLogHeader.printInitializeTaskContextHeader();\n        initializeTaskContext();\n\n        publishTaskRunningEvent();\n\n        TaskInstanceLogHeader.printLoadTaskInstancePluginHeader();\n        initializeTaskPlugin();\n\n        TaskInstanceLogHeader.printExecuteTaskHeader();\n\n        if (taskExecutionContext.getDryRun() == Flag.YES.getCode()) {\n            log.info(\"The task: {} is dryRun model, skip the trigger stage.\", taskExecutionContext.getTaskName());\n            transitTaskExecutorState(TaskExecutorState.SUCCEEDED);\n            return;\n        }\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-task-executor/src/main/java/org/apache/dolphinscheduler/task/executor/AbstractTaskExecutor.java#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only call start() once per executor instance; create a fresh executor for a retry","Check isStarted()/startFlag state before calling start()","If restart is needed, build a new task executor instance from the task context"],"exampleFix":"// before\nif (!taskExecutor.isStarted()) { taskExecutor.start(); }\ntaskExecutor.start(); // second call throws\n// after\nif (!taskExecutor.isStarted()) {\n    taskExecutor.start();\n}","handlingStrategy":"type-guard","validationCode":"if (taskExecutor.isStarted()) {\n    return; // or throw a controlled error at the call site\n}\ntaskExecutor.start();","typeGuard":"boolean canStart(ITaskExecutor te) {\n    return te != null && !te.isStarted();\n}","tryCatchPattern":"try {\n    taskExecutor.start();\n} catch (TaskExecutorRuntimeException e) {\n    if (!e.getMessage().contains(\"has already started\")) throw e;\n    // idempotent no-op: already started\n}","preventionTips":["Treat start() as one-shot; guard with an isStarted check","Never reuse an executor instance for retries — build a new one","Route all starts through the container rather than calling start manually"],"tags":["task-executor","lifecycle","idempotency"],"backgroundTag":"invalid-state-transition","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}