flowable/flowable-engine · error · FlowableException

Cannot find plan item with definition id '<planItemDefinitio

Error message

Cannot find plan item with definition id '<planItemDefinitionId>' in case definition with id '<caseDefinitionId>'

What it means

Flowable throws this FlowableException when a dynamic CMMN case modification cannot resolve a plan item in the loaded CMMN model by plan item definition id. resolvePlanItemFromCmmnModelWithDefinitionId looks up the element via CmmnModel.findPlanItemByPlanItemDefinitionId and aborts when no matching plan item exists in the target case definition.

Source

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

/**
 * @author Tijs Rademakers
 * @author Valentin Zickner
 */
public abstract class AbstractCmmnDynamicStateManager {

    protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
    
    protected CmmnEngineConfiguration cmmnEngineConfiguration;
    
    public AbstractCmmnDynamicStateManager(CmmnEngineConfiguration cmmnEngineConfiguration) {
        this.cmmnEngineConfiguration = cmmnEngineConfiguration;
    }

    protected PlanItem resolvePlanItemFromCmmnModelWithDefinitionId(String planItemDefinitionId, String caseDefinitionId) {
        CmmnModel cmmnModel = CaseDefinitionUtil.getCmmnModel(caseDefinitionId);
        PlanItem planItem = cmmnModel.findPlanItemByPlanItemDefinitionId(planItemDefinitionId);
        if (planItem == null) {
            throw new FlowableException("Cannot find plan item with definition id '" + planItemDefinitionId + "' in case definition with id '" + caseDefinitionId + "'");
        }
        return planItem;
    }

    protected PlanItem resolvePlanItemFromCmmnModel(CmmnModel cmmnModel, String planItemId, String caseDefinitionId) {
        PlanItem planItem = cmmnModel.findPlanItem(planItemId);
        if (planItem == null) {
            throw new FlowableException("Cannot find plan item '" + planItemId + "' in case definition with id '" + caseDefinitionId + "'");
        }
        return planItem;
    }

    protected void doMovePlanItemState(CaseInstanceChangeState caseInstanceChangeState, String originalCaseDefinitionId, CommandContext commandContext) {
        CaseInstanceEntityManager caseInstanceEntityManager = cmmnEngineConfiguration.getCaseInstanceEntityManager();
        CaseInstanceEntity caseInstance = caseInstanceEntityManager.findById(caseInstanceChangeState.getCaseInstanceId());
        
        Map<String, List<PlanItemInstanceEntity>> currentPlanItemInstances = retrievePlanItemInstances(caseInstanceChangeState.getCaseInstanceId());
        caseInstanceChangeState.setCurrentPlanItemInstances(currentPlanItemInstances);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify planItemDefinitionId exists in the deployed case's CMMN XML (<planItem> whose planItemDefinition has that id)
  2. Confirm the caseDefinitionId points to the case definition version that actually contains the plan item (check ACT_CMMN_CASEDEF / repository)
  3. Re-fetch the case definition and list its plan items (e.g. via the CmmnModel) to pick a valid id
  4. If the case model changed, update the change-state/migration request to use the new definition ids

Example fix

// before
changeStateBuilder.planItem("nonexistentStepId", "caseDef-1");
// after
CmmnModel model = CaseDefinitionUtil.getCmmnModel("caseDef-1");
if (model.findPlanItemByPlanItemDefinitionId("stepId") != null) {
    changeStateBuilder.planItem("stepId", "caseDef-1");
}
Defensive patterns

Strategy: validation

Validate before calling

CmmnModel model = CaseDefinitionUtil.getCmmnModel(caseDefinitionId);
if (model.findPlanItemByPlanItemDefinitionId(planItemDefinitionId) == null) {
    throw new IllegalArgumentException("Unknown planItemDefinitionId: " + planItemDefinitionId);
}

Type guard

boolean planItemExists = cmmnModel.findPlanItemByPlanItemDefinitionId(planItemDefinitionId) != null;

Try / catch

try {
    changeStateBuilder.planItem(planItemDefinitionId, caseDefinitionId);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Cannot find plan item")) {
        // refresh case definition ids and retry with corrected ids
    }
}

Prevention

When it happens

Trigger: Calling case modification/change-state APIs such as planItem(...) on CaseChangeStateRequest/builders with a planItemDefinitionId that does not exist in the case definition identified by caseDefinitionId — e.g. after redeploying a changed case model, using an id from a different case, or a typo in the definition id.

Common situations: Case migration between case definition versions where a plan item was renamed or removed; runtime operations referencing a stale case definition id after a new deployment; programmatically generated definition ids not matching the deployed CMMN XML.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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