{"record":{"id":"e0a799de1603d8ed","repo":"flowable/flowable-engine","slug":"the-task-cannot-be-deleted-because-is-part-of-a","errorCode":null,"errorMessage":"The ${task} cannot be deleted because is part of a running case instance","messagePattern":"The (.+?) cannot be deleted because is part of a running case instance","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/task/TaskHelper.java","lineNumber":74,"sourceCode":"        }\n\n        if (taskEntity.getAssignee() != null) {\n            addAssigneeIdentityLinks(taskEntity, cmmnEngineConfiguration);\n            fireAssignmentEvents(taskEntity, cmmnEngineConfiguration);\n        }\n\n    }\n    \n    public static void completeTask(TaskEntity task, String userId, CmmnEngineConfiguration cmmnEngineConfiguration) {\n        cmmnEngineConfiguration.getPlanItemInstanceEntityManager().updateHumanTaskPlanItemInstanceCompletedBy(task, userId);\n        internalDeleteTask(task, userId, null, false, true, cmmnEngineConfiguration);\n    }\n\n    public static void deleteTask(String taskId, String deleteReason, boolean cascade, CmmnEngineConfiguration cmmnEngineConfiguration) {\n        TaskEntity task = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);\n        if (task != null) {\n            if (task.getScopeId() != null && ScopeTypes.CMMN.equals(task.getScopeType())) {\n                throw new FlowableException(\"The \" + task + \" cannot be deleted because is part of a running case instance\");\n            } else if (task.getExecutionId() != null) {\n                throw new FlowableException(\"The \" + task + \" cannot be deleted because is part of a running process instance\");\n            }\n            deleteTask(task, deleteReason, cascade, true, cmmnEngineConfiguration);\n            \n        } else if (cascade) {\n            deleteHistoricTask(taskId, cmmnEngineConfiguration);\n        }\n    }\n    \n    public static void deleteTask(TaskEntity task, String deleteReason, boolean cascade, \n            boolean fireEvents, CmmnEngineConfiguration cmmnEngineConfiguration) {\n        \n        internalDeleteTask(task, null, deleteReason, cascade, fireEvents, cmmnEngineConfiguration);\n    }\n\n    protected static void internalDeleteTask(TaskEntity task, String userId, String deleteReason, boolean cascade, \n            boolean fireEvents, CmmnEngineConfiguration cmmnEngineConfiguration) {","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/task/TaskHelper.java#L56-L92","documentation":"TaskHelper.deleteTask(taskId, deleteReason, cascade, config) refuses to delete a standalone task that belongs to a running CMMN case instance (task.scopeId set and scopeType CMMN). Case tasks are managed by the case engine's lifecycle, so deleting them directly would corrupt case state; the caller must complete/terminate the plan item instead.","triggerScenarios":"Calling TaskService.deleteTask(taskId) (or TaskHelper.deleteTask) on a task whose getScopeId() != null and scopeType == ScopeTypes.CMMN, i.e. any task created by a human task plan item in an active case.","commonSituations":"Admin/cleanup jobs that purge stale tasks hitting CMMN-created tasks; custom task management UIs exposing delete on case tasks; migrating legacy cleanup scripts to a mixed process/case environment.","solutions":["Delete or terminate the owning case/plan item instead (CaseInstanceService/deleteCaseInstance or complete the plan item), letting the engine remove the task","Filter CMMN-scoped tasks out of bulk deletion logic: skip tasks where scopeId != null and scopeType == CMMN","If the case is actually finished, clean up via history deletion (deleteHistoricTask) rather than the runtime task","Use cascade=false only for standalone tasks; handle case tasks through the case runtime service"],"exampleFix":"// before\ntaskService.deleteTask(taskId, \"cleanup\");\n// after\nTaskEntity task = ...getTask(taskId);\nif (task.getScopeId() != null && ScopeTypes.CMMN.equals(task.getScopeType())) {\n    cmmnRuntimeService.deleteCaseInstance(task.getScopeId(), \"cleanup\");\n} else {\n    taskService.deleteTask(taskId, \"cleanup\");\n}","handlingStrategy":"validation","validationCode":"if (task.getScopeId() != null && ScopeTypes.CMMN.equals(task.getScopeType())) {\n    throw new IllegalArgumentException(\"task \" + task.getId() + \" belongs to case \" + task.getScopeId() + \"; delete the case instead\");\n}","typeGuard":"boolean isStandalone(Task t) { return t.getScopeId() == null && t.getExecutionId() == null; }","tryCatchPattern":"try { taskService.deleteTask(taskId, reason); } catch (FlowableException e) { if (e.getMessage().contains(\"running case instance\")) { cmmnRuntimeService.deleteCaseInstance(scopeId, reason); } else throw e; }","preventionTips":["Filter tasks by scopeId/scopeType before bulk deletes","Use case/runtime services to remove case-owned tasks","Audit admin delete endpoints to disallow scoped tasks"],"tags":["cmmn","task-lifecycle","flowable"],"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-14T05:17:10.506Z"}