flowable/flowable-engine · error · FlowableImageException
Could not find graphic info for decision service
Error message
Could not find graphic info for decision service: ${decisionServiceId} What it means
DefaultDecisionRequirementsDiagramGenerator.generateDecisionRequirementsDiagram throws FlowableImageException when a decision service in the DMN definition has no DI graphic info in the model. Diagram generation requires position/size metadata for every decision service.
Solutions
- Ensure the DMN XML contains DI elements (BPMNShape/BPMNEdge equivalents) for every decision service.
- Re-export the model from a DMN editor that emits diagram interchange data.
- Validate the DMN file's <DMNDI> section completeness before enabling diagram generation.
- Skip diagram generation for definitions lacking DI info.
Example fix
// before
if (decisionServiceInfo == null) { /* engine throws */ }
// after (caller-side guard)
boolean hasDi = dmnDefinition.getDecisionServices().stream()
.allMatch(ds -> dmnDefinition.getGraphicInfo(ds.getId()) != null);
if (hasDi) {
generator.generateDiagram(dmnDefinition);
} Defensive patterns
Strategy: validation
Validate before calling
boolean allDi = dmnDefinition.getDecisionServices().stream()
.allMatch(ds -> dmnDefinition.getGraphicInfo(ds.getId()) != null);
if (!allDi) { /* skip diagram generation or fix the model */ } Try / catch
try {
InputStream diagram = generator.generateDiagram(dmnDefinition);
} catch (FlowableImageException e) {
logger.warn("DRD lacks DI info; skipping diagram", e);
} Prevention
- Always author DMN with a complete DMNDI/DI section
- Re-export models from editors that emit diagram interchange data
- Validate DMN files at deploy time for DI completeness
When it happens
Trigger: Generating a decision requirements diagram for a DRD whose DMN XML lacks a BPMNShape/DI entry for one of its decision services, then drawing elements.
Common situations: Hand-authored or programmatically built DMN models missing the DI section; converters or tools that strip diagram interchange information; malformed DMN files from third-party editors.
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
- CaseDiagramGenerator already closed
- DecisionRequirementsDiagramGenerator already closed
- Error while generating case image
- Provided decision definition must have both key and…
- Provided decision definition must have its resource name…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/04aecc3f0a29db92.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-dmn-image-generator/src/main/java/org/flowable/dmn/image/impl/DefaultDecisionRequirementsDiagramGenerator.java:136
public BufferedImage generatePngImage(DmnDefinition dmnDefinition, double scaleFactor) {
return generateImage(dmnDefinition, "png", scaleFactor);
}
protected DefaultDecisionRequirementsDiagramCanvas generateDecisionRequirementsDiagram(DmnDefinition dmnDefinition, String imageType,
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
prepareDmnDefinition(dmnDefinition);
DefaultDecisionRequirementsDiagramCanvas decisionRequirementsDiagramCanvas = initDecisionRequirementsDiagramCanvas(dmnDefinition, imageType,
activityFontName, labelFontName, annotationFontName, customClassLoader);
// Draw elements
for (DecisionService decisionService : dmnDefinition.getDecisionServices()) {
GraphicInfo decisionServiceInfo = dmnDefinition.getGraphicInfo(decisionService.getId());
if (decisionServiceInfo == null) {
throw new FlowableImageException("Could not find graphic info for decision service: " + decisionService.getId());
}
List<GraphicInfo> decisionServiceDividerInfos = dmnDefinition.getDecisionServiceDividerGraphicInfo(decisionService.getId());
decisionRequirementsDiagramCanvas.drawDecisionService(decisionService.getName(), decisionServiceInfo, decisionServiceDividerInfos, scaleFactor);
for (DmnElementReference decisionRef : decisionService.getOutputDecisions()) {
Decision decision = dmnDefinition.getDecisionById(decisionRef.getParsedId());
// draw decisions
drawDecision(decisionRequirementsDiagramCanvas, dmnDefinition, decision, scaleFactor);
// draw information requirements
for (InformationRequirement informationRequirement : decision.getRequiredDecisions()) {
drawInformationRequirement(decisionRequirementsDiagramCanvas, dmnDefinition, informationRequirement, decision, scaleFactor);
}
}
for (DmnElementReference decisionRef : decisionService.getEncapsulatedDecisions()) {View on GitHub (pinned to d6d39ce1c6)