{"record":{"id":"4b730022c260f9b5","repo":"flowable/flowable-engine","slug":"no-sentry-found-for-reference-exitcriterion-gets","errorCode":null,"errorMessage":"No sentry found for reference ${exitCriterion.getSentryRef()} of exit criterion ${exitCriterion.getId()}","messagePattern":"No sentry found for reference (.+?) of exit criterion (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverter.java","lineNumber":626,"sourceCode":"                // Therefore only look for a sentry if it hasn't been set yet\n                Sentry sentry = entryCriterion.getParent().findSentry(entryCriterion.getSentryRef());\n                if (sentry != null) {\n                    entryCriterion.setSentry(sentry);\n                } else {\n                    throw new FlowableException(\"No sentry found for reference \"\n                            + entryCriterion.getSentryRef() + \" of entry criterion \" + entryCriterion.getId());\n                }\n            }\n        }\n    }\n\n    protected void resolveExitCriteriaSentry(HasExitCriteria hasExitCriteria) {\n        for (Criterion exitCriterion : hasExitCriteria.getExitCriteria()) {\n            Sentry sentry = exitCriterion.getParent().findSentry(exitCriterion.getSentryRef());\n            if (sentry != null) {\n                exitCriterion.setSentry(sentry);\n            } else {\n                throw new FlowableException(\"No sentry found for reference \"\n                        + exitCriterion.getSentryRef() + \" of exit criterion \" + exitCriterion.getId());\n            }\n        }\n    }\n\n    protected void processSentries(Stage planModelStage, PlanFragment planFragment) {\n        for (Sentry sentry : planFragment.getSentries()) {\n            for (SentryOnPart onPart : sentry.getOnParts()) {\n                PlanItem planItem = planModelStage.findPlanItemInPlanFragmentOrDownwards(onPart.getSourceRef());\n                if (planItem != null) {\n                    onPart.setSource(planItem);\n                } else {\n                    throw new FlowableException(\"Could not resolve on part source reference \"\n                            + onPart.getSourceRef() + \" of sentry \" + sentry.getId());\n                }\n            }\n        }\n","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverter.java#L608-L644","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make every exitCriterion's sentryRef match a <sentry> id declared in the same parent stage/plan fragment","Restore the deleted <sentry> or remove the orphan exit criterion","Validate with the Flowable modeler and XSD/conversion checks before deployment","Search the case XML for the unresolved sentryRef value to locate all broken references"],"exampleFix":"// before\n<exitCriterion sentryRef=\"exitSentry2\"/> <!-- exitSentry2 not in this stage -->\n// after\n<exitCriterion sentryRef=\"exitSentry1\"/> <!-- matches <sentry id=\"exitSentry1\"> in same stage -->","handlingStrategy":"validation","validationCode":"Set<String> sentryIds = collectIds(doc, \"sentry\");\nfor (Element c : doc.getElementsByTagName(\"exitCriterion\")) {\n    String ref = c.getAttribute(\"sentryRef\");\n    if (!sentryIds.contains(ref)) throw new DeploymentException(\"Unresolved exit sentryRef: \" + ref);\n}","typeGuard":null,"tryCatchPattern":"try {\n    repositoryService.createDeployment().addClasspathResource(\"case.cmmn.xml\").deploy();\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"No sentry found for reference\"))\n        log.error(\"Exit criterion with dangling sentryRef: \" + e.getMessage());\n    throw e;\n}","preventionTips":["When moving plan items between stages, recreate their exit criteria/sentries in the target stage","Run XSD validation plus a dry-run conversion/deployment before promoting case definitions","Use the Flowable modeler so sentry references stay linked automatically"],"tags":["cmmn","xml","model-validation","broken-reference"],"backgroundTag":"entity-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}