conductor-oss/conductor · error · IllegalArgumentException
Cannot archive task: {} of workflow: {} with non-terminal st
Error message
Cannot archive task: {} of workflow: {} with non-terminal status: {} What it means
Thrown by removeTaskIndex when archiveTask=true but the task status is non-terminal AND not SCHEDULED. SCHEDULED tasks are explicitly skipped (logged) because they may not have been canceled yet; every other non-terminal status (IN_PROGRESS, etc.) raises this IllegalArgumentException. Archiving a non-terminal task would persist an in-flight task as its final state.
Source
Thrown at core/src/main/java/com/netflix/conductor/core/dal/ExecutionDAOFacade.java:618
if (archiveTask) {
if (task.getStatus().isTerminal()) {
// Only allow archival if task is in terminal state
// DO NOT archive async, since if archival errors out, task data will be lost
indexDAO.updateTask(
workflow.getWorkflowId(),
task.getTaskId(),
new String[] {ARCHIVED_FIELD},
new Object[] {true});
} else if (task.getStatus() == TaskModel.Status.SCHEDULED) {
// SCHEDULED tasks may not have been canceled yet (e.g. if cancelNonTerminalTasks
// failed for this task). Skip archival to allow the rest of the workflow removal
// to proceed rather than blocking on a task that was never started.
LOGGER.warn(
"Skipping archival of task: {} of workflow: {} with SCHEDULED status",
task.getTaskId(),
workflow.getWorkflowId());
} else {
throw new IllegalArgumentException(
"Cannot archive task: "
+ task.getTaskId()
+ " of workflow: "
+ workflow.getWorkflowId()
+ " with non-terminal status: "
+ task.getStatus());
}
} else {
// Not archiving, remove task from index
indexDAO.asyncRemoveTask(workflow.getWorkflowId(), task.getTaskId());
}
}
public void extendLease(TaskModel taskModel) {
taskModel.setUpdateTime(System.currentTimeMillis());
executionDAO.updateTask(taskModel);
}
View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Ensure all tasks reach a terminal status before archiving the workflow (the cancelNonTerminalTasks step normally handles this).
- If a task is genuinely stuck, terminate it or force the workflow to a terminal state before removal.
- If archival is not required, remove with archiveWorkflow=false so tasks are deleted from the index rather than archived.
- Investigate why cancelNonTerminalTasks did not bring the offending task to terminal status.
Defensive patterns
Strategy: validation
Validate before calling
// Ensure task is terminal (or SCHEDULED) before archiving
TaskModel.Status s = task.getStatus();
if (!s.isTerminal() && s != TaskModel.Status.SCHEDULED) {
throw new IllegalArgumentException(
"Cannot archive task " + task.getTaskId()
+ " with non-terminal status " + s);
} Try / catch
try {
facade.removeWorkflow(id, true);
} catch (IllegalArgumentException e) {
// a task is non-terminal and not SCHEDULED -> cancel/terminate tasks first
} Prevention
- Run cancelNonTerminalTasks to completion before archiving a workflow.
- If a task cannot reach terminal status, terminate the workflow rather than archiving.
- Use archive=false when preservation of in-flight tasks is not required.
When it happens
Trigger: Calling workflow removal with archival on a workflow that contains a task still IN_PROGRESS (or any non-terminal, non-SCHEDULED status). The guard is the final else after checking terminal status and the SCHEDULED special case.
Common situations: A workflow is being archived while one of its tasks is still actively executing (e.g. an async/system task that has not completed). A stuck task that never reached terminal status. Archival invoked during an in-flight cancellation that has not propagated to all tasks.
Related errors
- Cannot archive workflow: %s with status: %s
- Task %s of workflow %s can not be serialized to json
- This method is not implemented in CassandraExecutionDAO. Ple
- Error creating %d tasks for workflow: %s
- Error updating task: %s in workflow: %s
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/2a4d9dd0e503d584.
Report an issue: GitHub.