{"record":{"id":"dafa27d2e87d979d","repo":"flowable/flowable-engine","slug":"the-task-cannot-be-deleted-because-is-part-of-a-dafa27","errorCode":null,"errorMessage":"The ${task} cannot be deleted because is part of a running case","messagePattern":"The (.+?) cannot be deleted because is part of a running case","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TaskHelper.java","lineNumber":574,"sourceCode":"    protected static void fireTaskDeletedEvent(TaskEntity task, CommandContext commandContext, FlowableEventDispatcher eventDispatcher) {\n        if (eventDispatcher != null && eventDispatcher.isEnabled()) {\n            ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\n            CommandContextUtil.getEventDispatcher(commandContext).dispatchEvent(\n                    FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_DELETED, task),\n                    processEngineConfiguration.getEngineCfgKey());\n        }\n    }\n\n    public static void deleteTask(String taskId, String deleteReason, boolean cascade) {\n        CommandContext commandContext = CommandContextUtil.getCommandContext();\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\n        TaskEntity task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);\n\n        if (task != null) {\n            if (task.getExecutionId() != null) {\n                throw new FlowableException(\"The \" + task + \" cannot be deleted because is part of a running process\");\n            } else 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\");\n            }\n\n            if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, task.getProcessDefinitionId())) {\n                Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();\n                compatibilityHandler.deleteTask(taskId, deleteReason, cascade);\n                return;\n            }\n\n            deleteTask(task, deleteReason, cascade, true, true);\n\n        } else if (cascade) {\n            deleteHistoricTask(taskId);\n        }\n    }\n\n    public static void deleteTasksByProcessInstanceId(String processInstanceId, String deleteReason, boolean cascade) {\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();\n        List<TaskEntity> tasks = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().findTasksByProcessInstanceId(processInstanceId);","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TaskHelper.java#L556-L592","documentation":"Same guard as the running-process case but for CMMN: TaskHelper.deleteTask throws when the task's scopeType is 'cmmn' and it has a scopeId, i.e. it belongs to a running case instance. Its lifecycle is controlled by the case engine, so direct deletion is rejected.","triggerScenarios":"Calling TaskService.deleteTask(taskId) on a task whose scopeId is set and scopeType is ScopeTypes.CMMN (a human task created by a running CMMN case).","commonSituations":"Deleting tasks in shared task lists without checking scopeType; cleanup jobs that assume all tasks are BPMN standalone tasks; mixed BPMN/CMMN deployments where CMMN-originated tasks slip through.","solutions":["Check task.getScopeType() before deleting and skip CMMN-scoped tasks.","End the task through the CMMN engine (complete it or terminate the case stage) instead of direct deletion.","Terminate the case instance via the CMMN runtime service (caseRuntimeService.terminateCaseInstance) if cleanup is the goal.","Filter task queries with taskCandidateOrAssigned without CMMN scope or add scopeType filters before performing deletions."],"exampleFix":"// before\ntaskService.deleteTask(taskId, \"cleanup\");\n// after\nTask t = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (t != null && !ScopeTypes.CMMN.equals(t.getScopeType())) {\n    taskService.deleteTask(taskId, \"cleanup\");\n}","handlingStrategy":"validation","validationCode":"Task t = taskService.createTaskQuery().taskId(taskId).singleResult();\nboolean deletable = t != null && !ScopeTypes.CMMN.equals(t.getScopeType());","typeGuard":"boolean isCmmnTask(Task t) { return t != null && ScopeTypes.CMMN.equals(t.getScopeType()); }","tryCatchPattern":"try { taskService.deleteTask(taskId, reason); } catch (FlowableException e) { if (e.getMessage().contains(\"running case\")) { /* route to CMMN engine */ } else throw e; }","preventionTips":["Always check scopeType in mixed BPMN/CMMN deployments","Handle CMMN tasks via the case runtime service, not TaskService.deleteTask","Exclude scoped tasks from cleanup jobs"],"tags":["flowable","cmmn","task","invalid-state-transition"],"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"}