flowable/flowable-engine · error · FlowableException

No matching plan item definition found for reference

Error message

No matching plan item definition found for reference ${planItem.getDefinitionRef()} of plan item ${planItem.getId()}

What it means

While post-processing the converted model, each PlanItem's definitionRef must resolve to a PlanItemDefinition in its parent stage or an ancestor stage. If planItem.getParentStage().findPlanItemDefinitionInStageOrUpwards(definitionRef) returns null, this FlowableException is thrown: the plan item references a definition that does not exist at or above its level.

Solutions

  1. Open the CMMN XML and make every planItem's definitionRef match the id of a planItemDefinition declared in the same or an ancestor stage
  2. Re-link the plan item in the Flowable modeler instead of hand-editing ids
  3. Validate the XML against the CMMN 1.1 XSD and run the conversion before deployment
  4. Search the file for the failing definitionRef value and correct or remove the orphan plan item

Example fix

// before
<planItem id="planTask1" definitionRef="task1"/> <!-- task1 deleted -->
// after
<planItem id="planTask1" definitionRef="humanTask1"/> <!-- matches existing definition id -->
Defensive patterns

Strategy: validation

Validate before calling

// Before deployment, check every planItem definitionRef resolves in the same or ancestor stage
Map<String, Element> defs = collectIdsByElementName(doc, "planItemDefinition"); // task/humanTask/case/sentry-def ids
for (Element planItem : doc.getElementsByTagName("planItem")) {
    String ref = planItem.getAttribute("definitionRef");
    if (!defs.containsKey(ref)) throw new DeploymentException("Unresolved definitionRef: " + ref);
}

Try / catch

try {
    repositoryService.createDeployment().addClasspathResource("case.cmmn.xml").deploy();
} catch (FlowableException e) {
    if (e.getMessage().startsWith("No matching plan item definition found"))
        log.error("Broken definitionRef in case model: " + e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Deploying CMMN XML where a <planItem definitionRef="..."> points to a definitionRef id that is not declared (or is declared only in a child stage or sibling), typically after renaming/deleting the referenced task/stage/event listener definition.

Common situations: Hand-editing or tool-generated CMMN with dangling definitionRef attributes, refactoring case definitions without updating plan items, copy-pasting plan items between stages/levels where the definition lives elsewhere.

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

Appendix: source

Thrown at modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverter.java:517

            for (PlanItemDefinition planItemDefinition : stage.getPlanItemDefinitions()) {
                if (planItemDefinition instanceof PlanFragment) {
                    processPlanFragment(cmmnModel, (PlanFragment) planItemDefinition);
                }
            }

            if (!stage.getExitCriteria().isEmpty()) {
                resolveExitCriteriaSentry(stage);
            }
        }
    }

    protected void processPlanItems(CmmnModel cmmnModel, PlanFragment planFragment) {
        for (PlanItem planItem : planFragment.getPlanItems()) {
            // Plan items are defined on the same level or in a higher parent stage, never in a child stage.
            Stage parentStage = planItem.getParentStage();
            PlanItemDefinition planItemDefinition = parentStage.findPlanItemDefinitionInStageOrUpwards(planItem.getDefinitionRef());
            if (planItemDefinition == null) {
                throw new FlowableException("No matching plan item definition found for reference "
                    + planItem.getDefinitionRef() + " of plan item " + planItem.getId());
            }

            planItem.setPlanItemDefinition(planItemDefinition);
            procesPlanItem(cmmnModel, planItem, planItemDefinition);

        }

    }

    protected void procesPlanItem(CmmnModel cmmnModel, PlanItem planItem, PlanItemDefinition planItemDefinition) {
        if (!planItem.getEntryCriteria().isEmpty()) {
            resolveEntryCriteria(planItem);
        }

        if (!planItem.getExitCriteria().isEmpty()) {
            resolveExitCriteriaSentry(planItem);
        }

View on GitHub (pinned to d6d39ce1c6)