flowable/flowable-engine · error · FlowableException

Plan item could not be found for <elementId>

Error message

Plan item could not be found for <elementId>

What it means

While verifying satisfied sentry parts during a plan item state change, an AVAILABLE plan item instance that has matched sentry parts must have its PlanItem model reference; if getPlanItem() is null the engine cannot evaluate entry criteria and throws this FlowableException. This indicates an internal model resolution failure.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/AbstractCmmnDynamicStateManager.java:614

                sentryInstanceMap.put(sentryPartInstanceEntity.getPlanItemInstanceId(), new ArrayList<>());
            }
            
            sentryInstanceMap.get(sentryPartInstanceEntity.getPlanItemInstanceId()).add(sentryPartInstanceEntity);
        }
        
        PlanItemInstanceEntityManager planItemInstanceEntityManager = cmmnEngineConfiguration.getPlanItemInstanceEntityManager();
        List<PlanItemInstanceEntity> planItemInstances = planItemInstanceEntityManager.findByCaseInstanceId(caseInstance.getId());
        
        CmmnDeploymentManager deploymentManager = cmmnEngineConfiguration.getDeploymentManager();
        CmmnModel targetCmmnModel = deploymentManager.resolveCaseDefinition(caseInstanceChangeState.getCaseDefinitionToMigrateTo()).getCmmnModel();
        
        for (PlanItemInstanceEntity planItemInstanceEntity : planItemInstances) {
            List<String> skipSentryPartInstanceForDeleteIds = new ArrayList<>();
            if (PlanItemInstanceState.AVAILABLE.equalsIgnoreCase(planItemInstanceEntity.getState()) && 
                    sentryInstanceMap.containsKey(planItemInstanceEntity.getId())) {
                
                if (planItemInstanceEntity.getPlanItem() == null) {
                    throw new FlowableException("Plan item could not be found for " + planItemInstanceEntity.getElementId());
                }
                
                if (planItemInstanceEntity.getPlanItem().getEntryCriteria().isEmpty()) {
                    continue;
                }
                
                for (Criterion criterion : planItemInstanceEntity.getPlanItem().getEntryCriteria()) {
                    verifySatisfiedSentryPartsForCriterion(criterion, planItemInstanceEntity, sentryInstanceMap, 
                            skipSentryPartInstanceForDeleteIds, false, targetCmmnModel, sentryPartInstanceEntityManager);
                }
                
            } else if (PlanItemInstanceState.ACTIVE.equalsIgnoreCase(planItemInstanceEntity.getState()) && 
                    sentryInstanceMap.containsKey(planItemInstanceEntity.getId())) {
                
                if (planItemInstanceEntity.getPlanItem() == null) {
                    throw new FlowableException("Plan item could not be found for " + planItemInstanceEntity.getElementId());
                }
                

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Redeploy the case definition containing the referenced elementId so the model can be resolved
  2. Migrate the case instance to a definition containing the element before doing dynamic state changes
  3. Check the case instance's case definition id vs the deployed model for version mismatch
  4. Clear/repair the inconsistent plan item instance rows for the case instance

Example fix

// before
cmmnRuntimeService.changePlanItemState(caseInstanceId, oldChangeState); // targets stale definition
// after
cmmnRuntimeService.setCaseInstanceCaseDefinition(caseInstanceId, newCaseDefinitionId); // or migrate first
cmmnRuntimeService.changePlanItemState(caseInstanceId, changeState);
Defensive patterns

Strategy: try-catch

Validate before calling

if (planItemInstanceEntity.getPlanItem() == null) {
    throw new IllegalStateException("Plan item model unresolved for element " + planItemInstanceEntity.getElementId());
}

Type guard

boolean hasResolvedPlanItem(PlanItemInstance pi) {
    return pi instanceof PlanItemInstanceEntity e && e.getPlanItem() != null;
}

Try / catch

try {
    cmmnRuntimeService.changePlanItemState(caseInstanceId, changeState);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Plan item could not be found")) {
        // migrate case instance to a definition containing the element, then retry
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: doMovePlanItemState / executeVerifySatisfiedSentryParts with an AVAILABLE plan item instance whose planItem reference is null (model lookup failed for the elementId) while sentry parts were satisfied.

Common situations: Corrupted or partially migrated case instance data referencing plan item ids absent from the deployed case definition; changing state across case definition versions where the element no longer exists.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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