flowable/flowable-engine · error · FlowableException

The ${task} cannot be deleted because is part of a running p

Error message

The ${task} cannot be deleted because is part of a running process instance

What it means

The process-instance twin of error 932: TaskHelper.deleteTask throws this when the task has an executionId, meaning it belongs to a running BPMN process instance. The engine manages such tasks' lifecycle; direct deletion is forbidden to keep execution and history consistent.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/task/TaskHelper.java:76

        if (taskEntity.getAssignee() != null) {
            addAssigneeIdentityLinks(taskEntity, cmmnEngineConfiguration);
            fireAssignmentEvents(taskEntity, cmmnEngineConfiguration);
        }

    }
    
    public static void completeTask(TaskEntity task, String userId, CmmnEngineConfiguration cmmnEngineConfiguration) {
        cmmnEngineConfiguration.getPlanItemInstanceEntityManager().updateHumanTaskPlanItemInstanceCompletedBy(task, userId);
        internalDeleteTask(task, userId, null, false, true, cmmnEngineConfiguration);
    }

    public static void deleteTask(String taskId, String deleteReason, boolean cascade, CmmnEngineConfiguration cmmnEngineConfiguration) {
        TaskEntity task = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
        if (task != null) {
            if (task.getScopeId() != null && ScopeTypes.CMMN.equals(task.getScopeType())) {
                throw new FlowableException("The " + task + " cannot be deleted because is part of a running case instance");
            } else if (task.getExecutionId() != null) {
                throw new FlowableException("The " + task + " cannot be deleted because is part of a running process instance");
            }
            deleteTask(task, deleteReason, cascade, true, cmmnEngineConfiguration);
            
        } else if (cascade) {
            deleteHistoricTask(taskId, cmmnEngineConfiguration);
        }
    }
    
    public static void deleteTask(TaskEntity task, String deleteReason, boolean cascade, 
            boolean fireEvents, CmmnEngineConfiguration cmmnEngineConfiguration) {
        
        internalDeleteTask(task, null, deleteReason, cascade, fireEvents, cmmnEngineConfiguration);
    }

    protected static void internalDeleteTask(TaskEntity task, String userId, String deleteReason, boolean cascade, 
            boolean fireEvents, CmmnEngineConfiguration cmmnEngineConfiguration) {
        
        if (!task.isDeleted()) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Delete the owning process instance instead (RuntimeService.deleteProcessInstance(executionId, reason)) so the engine cascades task deletion
  2. Skip execution-linked tasks in cleanup code by checking task.getExecutionId() != null before deleting
  3. If the process should continue but the task must go, remove the underlying activity/plan appropriately (e.g. change activity state or complete the task) rather than deleteTask
  4. For finished instances, purge via history services instead

Example fix

// before
taskService.deleteTask(taskId, "cleanup");
// after
TaskEntity task = ...getTask(taskId);
if (task.getExecutionId() != null) {
    runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "cleanup");
} else {
    taskService.deleteTask(taskId, "cleanup");
}
Defensive patterns

Strategy: validation

Validate before calling

if (task.getExecutionId() != null) {
    throw new IllegalArgumentException("task " + task.getId() + " belongs to process " + task.getProcessInstanceId() + "; delete the process instead");
}

Type guard

boolean isProcessTask(Task t) { return t.getExecutionId() != null; }

Try / catch

try { taskService.deleteTask(taskId, reason); } catch (FlowableException e) { if (e.getMessage().contains("running process instance")) { runtimeService.deleteProcessInstance(task.getProcessInstanceId(), reason); } else throw e; }

Prevention

When it happens

Trigger: Calling TaskService.deleteTask / TaskHelper.deleteTask on a task whose getExecutionId() != null, i.e. a user task created inside an active process instance (and not CMMN-scoped, which would hit the case variant first).

Common situations: Task cleanup scripts and admin endpoints deleting 'stuck' tasks that are actually process user tasks; tests deleting seeded tasks without terminating the process; shared task-delete code paths reused across BPMN and CMMN.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/f0d550c398c7cb38. Report an issue: GitHub.