{"record":{"id":"034eefdcbc6c3cbb","repo":"flowable/flowable-engine","slug":"casediagramgenerator-already-closed-034eef","errorCode":null,"errorMessage":"CaseDiagramGenerator already closed","messagePattern":"CaseDiagramGenerator already closed","errorType":"exception","errorClass":"FlowableImageException","httpStatus":null,"severity":"error","filePath":"modules/flowable-dmn-image-generator/src/main/java/org/flowable/dmn/image/impl/DefaultDecisionRequirementsDiagramCanvas.java","lineNumber":194,"sourceCode":"\n        LABEL_FONT = new Font(labelFontName, Font.ITALIC, 10);\n        ANNOTATION_FONT = new Font(annotationFontName, Font.PLAIN, FONT_SIZE);\n\n        try {\n         DECISION_IMAGE = ImageIO.read(ReflectUtil.getResource(\"org/flowable/icons/decision.png\", customClassLoader));\n        } catch (IOException e) {\n            LOGGER.warn(\"Could not load image for decision requirements diagram creation: {}\", e.getMessage());\n        }\n    }\n\n    /**\n     * Generates an image of what currently is drawn on the canvas.\n     *\n     * Throws an {@link FlowableImageException} when {@link #close()} is already called.\n     */\n    public InputStream generateImage(String imageType) {\n        if (closed) {\n            throw new FlowableImageException(\"CaseDiagramGenerator already closed\");\n        }\n\n        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {\n            ImageIO.write(decisionRequirementsDiagram, imageType, out);\n            return new ByteArrayInputStream(out.toByteArray());\n        } catch (IOException e) {\n            throw new FlowableImageException(\"Error while generating case image\", e);\n        }\n    }\n\n    /**\n     * Generates an image of what currently is drawn on the canvas.\n     *\n     * Throws an {@link FlowableImageException} when {@link #close()} is already called.\n     */\n    public BufferedImage generateBufferedImage(String imageType) {\n        if (closed) {\n            throw new FlowableImageException(\"DecisionRequirementsDiagramGenerator already closed\");","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-image-generator/src/main/java/org/flowable/dmn/image/impl/DefaultDecisionRequirementsDiagramCanvas.java#L176-L212","documentation":"DefaultDecisionRequirementsDiagramCanvas.generateImage throws FlowableImageException if generateImage is called after close() has been invoked. The canvas is single-use once closed; the internal diagram is no longer valid for image generation.","triggerScenarios":"Calling canvas.generateImage(imageType) after canvas.close() has already been called, e.g. generating two image formats from one closed canvas or reusing a canvas across requests.","commonSituations":"Generating both PNG and SVG/other formats from the same canvas object; storing the canvas in a cache and reusing it after a lifecycle close; double-close in cleanup code followed by retry.","solutions":["Call generateImage before close(), and close only once at the end.","Create a new canvas (regenerate the diagram) for each image you need.","Track the closed state in calling code and avoid reuse after close."],"exampleFix":"// before\ncanvas.generateImage(\"png\");\ncanvas.close();\ncanvas.generateImage(\"jpeg\"); // throws\n// after\ncanvas.generateImage(\"png\");\ncanvas.generateImage(\"jpeg\");\ncanvas.close();","handlingStrategy":"type-guard","validationCode":"if (canvas == null) throw new IllegalStateException(\"canvas not created\");\n// track closed state in your wrapper before calling generateImage","typeGuard":"boolean isOpen(DefaultDecisionRequirementsDiagramCanvas c) { return c != null && !c.isClosed(); }","tryCatchPattern":"try {\n    InputStream is = canvas.generateImage(\"png\");\n} catch (FlowableImageException e) {\n    logger.error(\"Canvas closed or image failed\", e);\n}","preventionTips":["Generate all images before calling close()","Create a fresh canvas per image format","Encapsulate canvas lifecycle in try-with-resources-style scope"],"tags":["dmn","diagram","lifecycle","closed-resource"],"backgroundTag":"invalid-state-transition","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"}