flowable/flowable-engine · error · FlowableObjectNotFoundException

Cannot find plan item instance for id ${planItemInstanceId}

Error message

Cannot find plan item instance for id ${planItemInstanceId}

What it means

FlowableObjectNotFoundException thrown in AbstractNeedsPlanItemInstanceCmd.execute when PlanItemInstanceEntityManager.findById returns null for the supplied id. The id was non-null but no plan item instance exists in the runtime tables (ACT_CMMN_RU_PLAN_ITEM_INST). Common when the plan item already completed or the id is from history.

Source

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

        this.planItemInstanceId = planItemInstanceId;
        this.variables = variables;
        this.formVariables = formVariables;
        this.formOutcome = formOutcome;
        this.formInfo = formInfo;
        this.localVariables = localVariables;
        this.transientVariables = transientVariables;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (planItemInstanceId == null) {
            throw new FlowableIllegalArgumentException("Plan item instance id is null");
        }

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        PlanItemInstanceEntity planItemInstanceEntity = cmmnEngineConfiguration.getPlanItemInstanceEntityManager().findById(planItemInstanceId);
        if (planItemInstanceEntity == null) {
            throw new FlowableObjectNotFoundException("Cannot find plan item instance for id " + planItemInstanceId, PlanItemInstanceEntity.class);
        }

        if (formInfo != null) {
            FormService formService = CommandContextUtil.getFormService(commandContext);
            if (formService == null) {
                throw new FlowableIllegalStateException("Form engine is not initialized");
            }

            Map<String, Object> variablesFromFormSubmission = formService.getVariablesFromFormSubmission(planItemInstanceEntity.getPlanItemDefinitionId(), 
                    planItemInstanceEntity.getPlanItemDefinitionType(), planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getCaseDefinitionId(), 
                    ScopeTypes.CMMN, formInfo, formVariables, formOutcome);

            FormFieldHandler formFieldHandler = cmmnEngineConfiguration.getFormFieldHandler();
            formFieldHandler.handleFormFieldsOnSubmit(formInfo, null, null, planItemInstanceEntity.getCaseInstanceId(), ScopeTypes.CMMN, variablesFromFormSubmission,
                    planItemInstanceEntity.getTenantId());

            planItemInstanceEntity.setVariables(variablesFromFormSubmission);
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Query cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(id).singleResult() first and check state is active before completing
  2. Handle double submissions idempotently in your client (disable buttons/track submitted ids)
  3. Use cmmnHistoryService for data about completed plan items
  4. Verify you are querying the correct engine/database/tenant

Example fix

// before
cmmnTaskService.completePlanItemPlanForm(planItemInstanceId, caseInstanceId, formInfo, variables, null);
// after
PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).singleResult();
if (pii == null || !PlanItemInstanceState.ACTIVE.equals(pii.getState())) {
    throw new IllegalStateException("Plan item " + planItemInstanceId + " is not active");
}
cmmnTaskService.completePlanItemPlanForm(planItemInstanceId, caseInstanceId, formInfo, variables, null);
Defensive patterns

Strategy: validation

Validate before calling

PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).singleResult();
if (pii == null) throw new IllegalStateException("Plan item instance " + planItemInstanceId + " not found or already completed");

Try / catch

try { cmmnTaskService.completePlanItemPlanForm(...); }
catch (FlowableObjectNotFoundException e) { log.info("Plan item {} already completed/removed", planItemInstanceId); }

Prevention

When it happens

Trigger: Completing/triggering a plan item that already reached a terminal state (completed/terminated/exited) and whose runtime row was removed; using a historic plan item instance id; wrong database or tenant; id typo.

Common situations: Double-submission of a form (second call after plan item completed); case instance terminated concurrently by another user; using planItemInstanceId from a completed case's history endpoint.

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