flowable/flowable-engine · critical · FlowableException

Could not find plan item instance for

Error message

Could not find plan item instance for 

What it means

Thrown by CompleteTaskCmd when the task's subScopeId points to a plan item instance that no longer exists in the CMMN database. The task is linked to a CMMN plan item (e.g. a case user task) but the plan item row is missing, so the engine cannot complete the plan item as part of completing the task. This indicates internal data inconsistency, typically a concurrently deleted/finished case.

Solutions

  1. Verify the case instance and plan item instance still exist and are active before completing the task.
  2. Avoid manual deletes on ACT_CMMN_* tables; use the engine's CaseInstanceService/terminate APIs to end cases.
  3. Check for concurrent termination of the case and handle FlowableException gracefully (task no longer completable).
  4. If data is inconsistent, re-seed from a consistent backup or use Flowable's database consistency checks.
Defensive patterns

Strategy: try-catch

Validate before calling

if (cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(task.getScopeId()).count() == 0) {
    throw new IllegalStateException("Case already terminated; task not completable");
}

Try / catch

try {
    cmmnTaskService.completeTask(taskId);
} catch (FlowableException e) {
    if (e.getMessage() != null && e.getMessage().contains("Could not find plan item instance")) {
        log.warn("Plan item for task {} vanished (case terminated concurrently?)", taskId);
        // surface stale-task state to the user instead of retrying
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Completing a CMMN task whose subScopeId no longer resolves via planItemInstanceEntityManager.findById: the case/plan item was terminated or deleted concurrently, or the database rows were partially removed/manipulated externally.

Common situations: Race between a user completing a task and another user terminating the case; custom SQL/manual cleanup of CMMN tables; restoring a database backup for only some tables; failed cascade deletes.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CompleteTaskCmd.java:98

            throw new FlowableIllegalArgumentException("Null task id");
        }
        
        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        TaskEntity taskEntity = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
        if (taskEntity == null) {
            throw new FlowableObjectNotFoundException("Could not find task entity for id " + taskId, TaskEntity.class);
        }
        
        if (StringUtils.isNotEmpty(taskEntity.getProcessInstanceId())) {
            throw new FlowableException(taskEntity + " is created by the process engine and should be completed via the process engine API");
        }
        
        String planItemInstanceId = taskEntity.getSubScopeId();
        PlanItemInstanceEntity planItemInstanceEntity = null;
        if (planItemInstanceId != null) {
            planItemInstanceEntity = cmmnEngineConfiguration.getPlanItemInstanceEntityManager().findById(planItemInstanceId);
            if (planItemInstanceEntity == null) {
                throw new FlowableException("Could not find plan item instance for " + taskEntity);
            }
        }
        
        if (variables != null) {
            taskEntity.setVariables(variables);
        }
        if (variablesLocal != null) {
            taskEntity.setVariablesLocal(variablesLocal);
        }
        if (transientVariables != null) {
            taskEntity.setTransientVariables(transientVariables);
        }
        if (transientVariablesLocal != null) {
            taskEntity.setTransientVariablesLocal(transientVariablesLocal);
        }

        logUserTaskCompleted(taskEntity, cmmnEngineConfiguration);
        

View on GitHub (pinned to d6d39ce1c6)