apache/dolphinscheduler · warning · ServiceException
The workflow instance: %s state is %s, cannot recovery
Error message
The workflow instance: %s state is %s, cannot recovery
What it means
Raised in RecoverSuspendedWorkflowInstanceExecutorDelegate.execute when the workflow instance fetched from the registry is not in a suspended/paused state. Recovery-from-suspend only applies to suspended instances; any other state (running, finished, failed, killed) makes recovery invalid, so the executor refuses with the instance id and its current state.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/executor/workflow/RecoverSuspendedWorkflowInstanceExecutorDelegate.java:46
import org.apache.dolphinscheduler.registry.api.RegistryClient;
import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RecoverSuspendedWorkflowInstanceExecutorDelegate
implements
IExecutorDelegate<RecoverSuspendedWorkflowInstanceExecutorDelegate.RecoverSuspendedWorkflowInstanceOperation, Void> {
@Autowired
private RegistryClient registryClient;
@Override
public Void execute(RecoverSuspendedWorkflowInstanceOperation workflowInstanceControlRequest) {
final WorkflowInstance workflowInstance = workflowInstanceControlRequest.workflowInstance;
if (!workflowInstance.getState().isPaused() && !workflowInstance.getState().isStopped()) {
throw new ServiceException(
String.format("The workflow instance: %s state is %s, cannot recovery", workflowInstance.getName(),
workflowInstance.getState()));
}
final Server masterServer = registryClient.getRandomServer(RegistryNodeType.MASTER).orElse(null);
if (masterServer == null) {
throw new ServiceException("no master server available");
}
final WorkflowInstanceRecoverSuspendTasksRequest recoverSuspendTaskRequest =
WorkflowInstanceRecoverSuspendTasksRequest.builder()
.workflowInstanceId(workflowInstance.getId())
.userId(workflowInstanceControlRequest.executeUser.getId())
.build();
final WorkflowInstanceRecoverSuspendTasksResponse recoverSuspendTaskResponse = Clients
.withService(IWorkflowControlClient.class)
.withHost(masterServer.getHost() + ":" + masterServer.getPort())
.triggerFromSuspendTasks(recoverSuspendTaskRequest);
if (!recoverSuspendTaskResponse.isSuccess()) {View on GitHub (pinned to 02eac45a1b)
Solutions
- Check the instance state before recovering: only paused/stopped instances qualify
- Refresh instance status — it may already have been resumed
- Use recover-from-failed-tasks for failure states and kill-recovery for killed states instead
- Catch this validation error in automation and treat it as a no-op when the instance already resumed
Example fix
// before
api.recoverSuspendedWorkflowInstance(instanceId, userId);
// after
WorkflowInstance wf = api.queryWorkflowInstance(instanceId);
if (wf.getState().isPaused() || wf.getState().isStopped()) {
api.recoverSuspendedWorkflowInstance(instanceId, userId);
} Defensive patterns
Strategy: validation
Validate before calling
WorkflowExecutionStatus st = workflowInstance.getState();
if (!st.isPaused() && !st.isStopped()) {
throw new IllegalStateException("State " + st + " is not recoverable from suspension");
} Type guard
boolean recoverableFromSuspend(WorkflowInstance wf) { return wf.getState().isPaused() || wf.getState().isStopped(); } Try / catch
try { delegate.recoverSuspended(op); } catch (ServiceException e) { if (e.getMessage().contains("cannot recovery")) { log.info("Instance not paused/stopped; skipping"); } else { throw e; } } Prevention
- Only offer 'recover suspended' for paused/stopped instances in the UI
- Refresh instance state before recovery actions
- Use the matching recovery API per state (failure vs suspended vs killed)
- In automation, re-query state after any pause/stop before recovery
When it happens
Trigger: RecoverSuspendedWorkflowInstanceExecutorDelegate.execute is called for an instance with state like running, success, failure, or killed — isPaused() and isStopped() both false.
Common situations: Recovering an already-recovered instance (now running); user clicks 'recover suspended' on a killed instance instead of using the correct recovery path; stale UI state after someone else resumed the workflow; scripts using the wrong recovery endpoint for failed tasks.
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
- The workflow instance: %s status is %s, can not be recovered
- The workflow instance: %s status is %s, can not pause
- Recover workflow instance failed: %s
- no master server available
- Backfill workflow failed: %s
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/5cc1588d73e32a4d.
Report an issue: GitHub.