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

  1. Ensure the DMN XML contains DI elements (BPMNShape/BPMNEdge equivalents) for every decision service.
  2. Re-export the model from a DMN editor that emits diagram interchange data.
  3. Validate the DMN file's <DMNDI> section completeness before enabling diagram generation.
  4. 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

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


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)