{"record":{"id":"b95a6ed68d3f2bca","repo":"flowable/flowable-engine","slug":"task-taskid-is-already-deleted","errorCode":null,"errorMessage":"Task ${taskId} is already deleted","messagePattern":"Task (.+?) is already deleted","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ActivateTaskCmd.java","lineNumber":58,"sourceCode":"        this.userId = userId;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        \n        if (taskId == null) {\n            throw new FlowableIllegalArgumentException(\"taskId is null\");\n        }\n\n        TaskEntity task = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);\n\n        if (task == null) {\n            throw new FlowableObjectNotFoundException(\"Cannot find task with id \" + taskId, Task.class);\n        }\n\n        if (task.isDeleted()) {\n            throw new FlowableException(\"Task \" + taskId + \" is already deleted\");\n        }\n\n        if (!task.isSuspended()) {\n            throw new FlowableException(\"Task \" + taskId + \" is not suspended, so can't be activated\");\n        }\n        \n        Clock clock = cmmnEngineConfiguration.getClock();\n        Date updateTime = clock.getCurrentTime();\n        task.setSuspendedTime(null);\n        task.setSuspendedBy(null);\n        if (task.getInProgressStartTime() != null) {\n            task.setState(Task.IN_PROGRESS);\n        } else if (task.getClaimTime() != null) {\n            task.setState(Task.CLAIMED);\n        } else {\n            task.setState(Task.CREATED);\n        }\n        task.setSuspensionState(SuspensionState.ACTIVE.getStateCode());","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ActivateTaskCmd.java#L40-L76","documentation":"Plain FlowableException thrown by ActivateTaskCmd.execute when the task exists but is already marked deleted (task.isDeleted()). Activation is only meaningful for suspended live tasks; a deleted task cannot be re-activated, so the command fails fast. This typically indicates the case instance was terminated and the task was cascaded to deleted.","triggerScenarios":"Calling activateTask on a task belonging to a terminated/completed case instance whose tasks were deleted; a concurrent delete completed between the task lookup and the isDeleted check; activating tasks after the case ended.","commonSituations":"Bulk activation scripts running after a case was terminated elsewhere; race between a user terminating a case and a worker activating its suspended tasks; retry logic replaying activation for tasks removed by cleanup.","solutions":["Skip tasks whose state indicates deletion; re-query the task right before activation and bail out if deleted or absent","Handle the FlowableException (message \"Task <id> is already deleted\") idempotently in worker code","Check the parent case instance state before activating its tasks","Avoid re-running activation batches over completed/terminated cases"],"exampleFix":"// before\ncmmnTaskService.activateTask(taskId); // throws if task deleted\n// after\nTask task = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (task != null && task.isSuspended() && !task.isDeleted()) {\n    cmmnTaskService.activateTask(taskId);\n} else {\n    logger.info(\"Task {} not activatable (missing/suspended/deleted); skipping\", taskId);\n}","handlingStrategy":"validation","validationCode":"Task t = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (t == null || t.isDeleted()) throw new IllegalStateException(\"Task \" + taskId + \" is deleted or missing; cannot activate\");","typeGuard":null,"tryCatchPattern":"try { cmmnTaskService.activateTask(taskId); }\ncatch (FlowableException e) { if (e.getMessage() != null && e.getMessage().endsWith(\"is already deleted\")) { log.info(\"Task {} already deleted; skipping\", taskId); } else { throw e; } }","preventionTips":["Check the parent case instance state before activating its tasks","Re-read the task immediately before activation to shrink race windows","Make bulk activation idempotent against deleted tasks","Match on the exception message carefully — this error uses FlowableException, not a typed not-found/illegal-argument class"],"tags":["flowable","cmmn","task","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}