flowable/flowable-engine · error · FlowableObjectNotFoundException

plan item instance ${planItemInstanceId} doesn't exist

Error message

plan item instance ${planItemInstanceId} doesn't exist

What it means

GetPlanItemVariableInstancesCmd throws FlowableObjectNotFoundException ('plan item instance <id> doesn't exist') when the PlanItemInstanceEntityManager findById returns null after argument validation succeeds. The caller provided a syntactically valid id, but no such live plan item instance exists in the runtime store.

Source

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

    
    protected String planItemInstanceId;

    public GetPlanItemVariableInstancesCmd(String planItemInstanceId) {
        this.planItemInstanceId = planItemInstanceId;
    }

    @Override
    public Map<String, VariableInstance> execute(CommandContext commandContext) {

        // Verify existence of execution
        if (planItemInstanceId == null) {
            throw new FlowableIllegalArgumentException("planItemInstanceId is null");
        }

        PlanItemInstanceEntity planItemInstance = CommandContextUtil.getPlanItemInstanceEntityManager(commandContext).findById(planItemInstanceId);

        if (planItemInstance == null) {
            throw new FlowableObjectNotFoundException("plan item instance " + planItemInstanceId + " doesn't exist", PlanItemInstance.class);
        }

        return planItemInstance.getVariableInstancesLocal();
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pre-check existence with createPlanItemInstanceQuery().planItemInstanceId(id).singleResult() and handle null gracefully.
  2. For ended items, retrieve variables from history (cmmnHistoryService historic variable instance queries).
  3. Re-acquire current plan item ids from the running case instance before reading variables.
  4. Ensure all clients operate against the same engine database and schema.

Example fix

// before
Map<String, VariableInstance> vars = cmmnRuntimeService.getPlanItemVariableInstances(planItemId);
// after
PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemId).singleResult();
Map<String, VariableInstance> vars = (pii != null) ? cmmnRuntimeService.getPlanItemVariableInstances(planItemId) : Collections.emptyMap();
Defensive patterns

Strategy: try-catch

Validate before calling

PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).singleResult();
if (pii == null) return Collections.emptyMap();

Type guard

boolean planItemInstanceExists(String id) {
    return cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(id).count() > 0;
}

Try / catch

try {
    vars = cmmnRuntimeService.getPlanItemVariableInstances(planItemInstanceId);
} catch (FlowableObjectNotFoundException e) {
    log.warn("Plan item {} no longer exists; using history", planItemInstanceId);
    vars = variablesFromHistory(planItemInstanceId);
}

Prevention

When it happens

Trigger: Reading all local variables of a plan item that has completed, been terminated, or whose parent case finished; stale ids from earlier deployments or prior test data; wrong database/environment; id-type confusion with case or stage ids.

Common situations: Aggregation jobs walking old plan item snapshots; UIs holding ids after case completion; concurrent termination while variables were being read; data cleanup jobs removing runtime rows mid-flight.

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/7fc9122d8a0ecfdf. Report an issue: GitHub.