{"record":{"id":"e57b3496b3def855","repo":"conductor-oss/conductor","slug":"cannot-archive-workflow-s-with-status-s","errorCode":null,"errorMessage":"Cannot archive workflow: %s with status: %s","messagePattern":"Cannot archive workflow: (.+?) with status: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/netflix/conductor/core/dal/ExecutionDAOFacade.java","lineNumber":437,"sourceCode":"        try {\n            queueDAO.remove(DECIDER_QUEUE, workflowId);\n        } catch (Exception e) {\n            LOGGER.info(\"Error removing workflow: {} from decider queue\", workflowId, e);\n        }\n    }\n\n    private void removeWorkflowIndex(WorkflowModel workflow, boolean archiveWorkflow)\n            throws JsonProcessingException {\n        if (archiveWorkflow) {\n            if (workflow.getStatus().isTerminal()) {\n                // Only allow archival if workflow is in terminal state\n                // DO NOT archive async, since if archival errors out, workflow data will be lost\n                indexDAO.updateWorkflow(\n                        workflow.getWorkflowId(),\n                        new String[] {RAW_JSON_FIELD, ARCHIVED_FIELD},\n                        new Object[] {objectMapper.writeValueAsString(workflow), true});\n            } else {\n                throw new IllegalArgumentException(\n                        String.format(\n                                \"Cannot archive workflow: %s with status: %s\",\n                                workflow.getWorkflowId(), workflow.getStatus()));\n            }\n        } else {\n            // Not archiving, also remove workflow from index\n            indexDAO.asyncRemoveWorkflow(workflow.getWorkflowId());\n        }\n    }\n\n    public void removeWorkflowWithExpiry(\n            String workflowId, boolean archiveWorkflow, int ttlSeconds) {\n        try {\n            WorkflowModel workflow = getWorkflowModelFromDataStore(workflowId, true);\n\n            try {\n                removeWorkflowIndex(workflow, archiveWorkflow);\n            } catch (NotFoundException e) {","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/com/netflix/conductor/core/dal/ExecutionDAOFacade.java#L419-L455","documentation":"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.","triggerScenarios":"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().","commonSituations":"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).","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."],"exampleFix":"// before - archive a still-running workflow\nfacade.removeWorkflow(id, /* archiveWorkflow */ true, ttl);\n// after - terminate first, then archive, or skip archival\nfacade.terminateWorkflow(id, reason);\nfacade.removeWorkflow(id, /* archiveWorkflow */ true, ttl);","handlingStrategy":"validation","validationCode":"// Ensure terminal status before archiving\nif (!workflow.getStatus().isTerminal()) {\n    throw new IllegalArgumentException(\n        \"Cannot archive workflow \" + workflow.getWorkflowId()\n            + \" with non-terminal status \" + workflow.getStatus());\n}","typeGuard":null,"tryCatchPattern":"try {\n    facade.removeWorkflow(id, true);\n} catch (IllegalArgumentException e) {\n    // workflow not terminal -> terminate first or remove without archiving\n}","preventionTips":["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."],"tags":["workflow","archival","state-machine","illegal-argument"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}