conductor-oss/conductor · error · IllegalArgumentException
Cannot archive workflow: %s with status: %s
Error message
Cannot archive workflow: %s with status: %s
What it means
Thrown by removeWorkflowIndex when archiveWorkflow=true but workflow.getStatus().isTerminal() is false. Archival copies the workflow into the index as the durable record, and Conductor only allows archiving workflows that have reached a terminal state (COMPLETED, FAILED, TERMINATED, etc.). Archiving a running workflow would freeze an incomplete snapshot as the 'final' record.
Source
Thrown at core/src/main/java/com/netflix/conductor/core/dal/ExecutionDAOFacade.java:437
try {
queueDAO.remove(DECIDER_QUEUE, workflowId);
} catch (Exception e) {
LOGGER.info("Error removing workflow: {} from decider queue", workflowId, e);
}
}
private void removeWorkflowIndex(WorkflowModel workflow, boolean archiveWorkflow)
throws JsonProcessingException {
if (archiveWorkflow) {
if (workflow.getStatus().isTerminal()) {
// Only allow archival if workflow is in terminal state
// DO NOT archive async, since if archival errors out, workflow data will be lost
indexDAO.updateWorkflow(
workflow.getWorkflowId(),
new String[] {RAW_JSON_FIELD, ARCHIVED_FIELD},
new Object[] {objectMapper.writeValueAsString(workflow), true});
} else {
throw new IllegalArgumentException(
String.format(
"Cannot archive workflow: %s with status: %s",
workflow.getWorkflowId(), workflow.getStatus()));
}
} else {
// Not archiving, also remove workflow from index
indexDAO.asyncRemoveWorkflow(workflow.getWorkflowId());
}
}
public void removeWorkflowWithExpiry(
String workflowId, boolean archiveWorkflow, int ttlSeconds) {
try {
WorkflowModel workflow = getWorkflowModelFromDataStore(workflowId, true);
try {
removeWorkflowIndex(workflow, archiveWorkflow);
} catch (NotFoundException e) {View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Terminate the workflow first (e.g. via the terminate API) so it reaches a terminal status, then archive.
- If you just want to remove it without archiving, call removeWorkflow with archiveWorkflow=false.
- If the workflow is genuinely stuck and will not terminate, investigate the decider/sweeper rather than forcing archival.
Example fix
// before - archive a still-running workflow facade.removeWorkflow(id, /* archiveWorkflow */ true, ttl); // after - terminate first, then archive, or skip archival facade.terminateWorkflow(id, reason); facade.removeWorkflow(id, /* archiveWorkflow */ true, ttl);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure terminal status before archiving
if (!workflow.getStatus().isTerminal()) {
throw new IllegalArgumentException(
"Cannot archive workflow " + workflow.getWorkflowId()
+ " with non-terminal status " + workflow.getStatus());
} Try / catch
try {
facade.removeWorkflow(id, true);
} catch (IllegalArgumentException e) {
// workflow not terminal -> terminate first or remove without archiving
} Prevention
- Only call the archive path on workflows confirmed to be in a terminal state.
- Terminate running workflows before cleanup.
- Use archive=false when you do not need to preserve the archived raw JSON.
When it happens
Trigger: Calling removeWorkflow(id, archiveWorkflow=true) while the workflow is still RUNNING, PAUSED, or in any non-terminal status. The check is purely on workflow.getStatus().isTerminal().
Common situations: A cleanup/sweeper job attempts to archive and remove a long-running or stuck workflow. A manual operator script calls the archive path on a workflow that was never terminated. A race where the workflow transitioned out of terminal status (should not happen, but indicates a state bug).
Related errors
- Cannot archive task: {} of workflow: {} with non-terminal st
- Workflow can not be serialized to json
- Task %s of workflow %s can not be serialized to json
- Task %s not found
- Error creating workflow: %s
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/e57b3496b3def855.
Report an issue: GitHub.