flowable/flowable-engine · error · FlowableException

No sentry found for reference

Error message

No sentry found for reference ${entryCriterion.getSentryRef()} of entry criterion ${entryCriterion.getId()}

What it means

During post-processing, each entry criterion's sentryRef must resolve to a <sentry> element declared in the same plan fragment/stage (its parent). If findSentry(sentryRef) returns null, this FlowableException is thrown: the entry criterion points to a sentry that does not exist.

Solutions

  1. Ensure every entryCriterion's sentryRef equals the id of a <sentry> declared within the same plan fragment/stage
  2. Re-add the missing <sentry> element or delete the orphan entry criterion
  3. Re-verify the case in the Flowable modeler so references are kept consistent
  4. Validate the file (XSD + conversion) before deployment to catch dangling refs early

Example fix

// before
<entryCriterion sentryRef="sentryOld"/> <!-- sentryOld removed -->
// after
<entryCriterion sentryRef="sentry1"/> <!-- matches <sentry id="sentry1"> in same stage -->
Defensive patterns

Strategy: validation

Validate before calling

Set<String> sentryIds = collectIds(doc, "sentry");
for (Element c : doc.getElementsByTagName("entryCriterion")) {
    String ref = c.getAttribute("sentryRef");
    if (!sentryIds.contains(ref)) throw new DeploymentException("Unresolved entry 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("Entry criterion with dangling sentryRef: " + e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Deploying CMMN XML where <entryCriterion sentryRef="..."> references a sentry id that was deleted, renamed, declared in a different stage/plan fragment, or never defined.

Common situations: Removing sentries while leaving criteria behind, refactoring case diagrams in external tools, copy-pasting plan items with their criteria but not their sentries, and typos in sentryRef.

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/01cc629e01f5f148. Report an issue: GitHub.

Appendix: source

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

            if (planItem.getItemControl().getParentCompletionRule() == null) {
                ParentCompletionRule parentCompletionRule = new ParentCompletionRule();
                parentCompletionRule.setType(ParentCompletionRule.IGNORE);

                planItem.getItemControl().setParentCompletionRule(parentCompletionRule);
            }
        }
    }

    protected void resolveEntryCriteria(HasEntryCriteria hasEntryCriteria) {
        for (Criterion entryCriterion : hasEntryCriteria.getEntryCriteria()) {
            if (entryCriterion.getSentry() == null) {
                // The timer event listener creates a fake sentry for the planItemStartTrigger.
                // 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());
            }
        }
    }

View on GitHub (pinned to d6d39ce1c6)