apache/dolphinscheduler · error · IllegalStateException

"WorkflowSerialCoordinator is already started"

Error message

"WorkflowSerialCoordinator is already started"

What it means

WorkflowSerialCoordinator.start() is guarded so it can only be started once; calling it again when the started flag is set throws this IllegalStateException. This protects the single internal daemon thread that polls serial commands.

Source

Thrown at dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/serial/WorkflowSerialCoordinator.java:80

    @Autowired
    private SerialCommandDiscardHandler serialCommandDiscardHandler;

    @Autowired
    private SerialCommandPriorityHandler serialCommandPriorityHandler;

    private volatile boolean flag = false;

    private Thread internalThread;

    private static final int DEFAULT_FETCH_SIZE = 1000;

    private static final int DEFAULT_FETCH_INTERVAL_SECONDS = 5;

    @Override
    public synchronized void start() {
        log.info("WorkflowSerialCoordinator starting...");
        if (flag) {
            throw new IllegalStateException("WorkflowSerialCoordinator is already started");
        }
        if (internalThread != null) {
            throw new IllegalStateException("InternalThread is already started");
        }
        flag = true;
        internalThread = new BaseDaemonThread(this::doStart) {
        };
        internalThread.setName("WorkflowSerialCoordinator-Thread");
        internalThread.start();
        log.info("WorkflowSerialCoordinator started...");
    }

    private void doStart() {
        while (flag) {
            try {
                final StopWatch workflowSerialCoordinatorRoundCost = StopWatch.createStarted();
                final List<SerialCommandsGroup> serialCommandsGroups = fetchSerialCommands();
                serialCommandsGroups.forEach(this::handleSerialCommand);

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Ensure start() is invoked once per coordinator instance
  2. Check for duplicate bean initialization in Spring config/component scanning
  3. Create a new coordinator instance before restarting
  4. Guard calls with the coordinator's own lifecycle state

Example fix

// before
coordinator.start();
coordinator.start(); // throws
// after
if (!coordinator.isStarted()) coordinator.start();
Defensive patterns

Strategy: validation

Validate before calling

if (coordinatorStarted) { /* skip start */ } else { coordinator.start(); coordinatorStarted = true; }

Type guard

boolean canStart(WorkflowSerialCoordinator c) { return !c.isStarted() && !c.isClosed(); }

Try / catch

try { coordinator.start(); } catch (IllegalStateException e) { log.warn("coordinator already started: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling start() a second time on the same coordinator instance, e.g. duplicate lifecycle start from Spring context refresh or manual re-initialization.

Common situations: Misconfigured bean lifecycle causing double start, tests calling start() repeatedly without recreating the object.

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/009fe91aa2063182. Report an issue: GitHub.