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
- Ensure start() is invoked once per coordinator instance
- Check for duplicate bean initialization in Spring config/component scanning
- Create a new coordinator instance before restarting
- 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
- Call start() exactly once per instance lifecycle
- Avoid duplicate Spring bean initialization
- Create a new instance for restarts
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
- "InternalThread is already started"
- TaskExecutionContextCreateException(ex.getMessage())
- CommandDuplicateHandleException(command)
- "The post SerialCommand except WAITING state but -> " + seri
- "SerialCommand with ExecutionType=PARALLEL is not supported,
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/009fe91aa2063182.
Report an issue: GitHub.