flowable/flowable-engine · error · FlowableException

No sentry found for reference

Error message

No sentry found for reference ${exitCriterion.getSentryRef()} of exit criterion ${exitCriterion.getId()}

What it means

Analogous to entry criteria, each exit criterion's sentryRef must resolve to a Sentry in the same parent element (stage or plan fragment). If it cannot be found, resolveExitCriteriaSentry throws this FlowableException during model post-processing.

Solutions

  1. Make every exitCriterion's sentryRef match a <sentry> id declared in the same parent stage/plan fragment
  2. Restore the deleted <sentry> or remove the orphan exit criterion
  3. Validate with the Flowable modeler and XSD/conversion checks before deployment
  4. Search the case XML for the unresolved sentryRef value to locate all broken references

Example fix

// before
<exitCriterion sentryRef="exitSentry2"/> <!-- exitSentry2 not in this stage -->
// after
<exitCriterion sentryRef="exitSentry1"/> <!-- matches <sentry id="exitSentry1"> in same stage -->
Defensive patterns

Strategy: validation

Validate before calling

Set<String> sentryIds = collectIds(doc, "sentry");
for (Element c : doc.getElementsByTagName("exitCriterion")) {
    String ref = c.getAttribute("sentryRef");
    if (!sentryIds.contains(ref)) throw new DeploymentException("Unresolved exit sentryRef: " + ref);
}

Try / catch

try {
    repositoryService.createDeployment().addClasspathResource("case.cmmn.xml").deploy();
} catch (FlowableException e) {
    if (e.getMessage().startsWith("No sentry found for reference"))
        log.error("Exit criterion with dangling sentryRef: " + e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Deploying CMMN XML where <exitCriterion sentryRef="..."> references a non-existent, renamed, or out-of-scope sentry id on a plan item, stage, or plan fragment.

Common situations: Deleting a sentry used by exit criteria, moving plan items across stages (sentries are not shared across levels), hand-editing XML, or importing CMMN from third-party modeling tools with unlinked references.

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

Appendix: source

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

                // Therefore only look for a sentry if it hasn't been set yet
                Sentry sentry = entryCriterion.getParent().findSentry(entryCriterion.getSentryRef());
                if (sentry != null) {
                    entryCriterion.setSentry(sentry);
                } else {
                    throw new FlowableException("No sentry found for reference "
                            + entryCriterion.getSentryRef() + " of entry criterion " + entryCriterion.getId());
                }
            }
        }
    }

    protected void resolveExitCriteriaSentry(HasExitCriteria hasExitCriteria) {
        for (Criterion exitCriterion : hasExitCriteria.getExitCriteria()) {
            Sentry sentry = exitCriterion.getParent().findSentry(exitCriterion.getSentryRef());
            if (sentry != null) {
                exitCriterion.setSentry(sentry);
            } else {
                throw new FlowableException("No sentry found for reference "
                        + exitCriterion.getSentryRef() + " of exit criterion " + exitCriterion.getId());
            }
        }
    }

    protected void processSentries(Stage planModelStage, PlanFragment planFragment) {
        for (Sentry sentry : planFragment.getSentries()) {
            for (SentryOnPart onPart : sentry.getOnParts()) {
                PlanItem planItem = planModelStage.findPlanItemInPlanFragmentOrDownwards(onPart.getSourceRef());
                if (planItem != null) {
                    onPart.setSource(planItem);
                } else {
                    throw new FlowableException("Could not resolve on part source reference "
                            + onPart.getSourceRef() + " of sentry " + sentry.getId());
                }
            }
        }

View on GitHub (pinned to d6d39ce1c6)