flowable/flowable-engine · error · FlowableImageException
DecisionRequirementsDiagramGenerator already closed
Error message
DecisionRequirementsDiagramGenerator already closed
What it means
DefaultDecisionRequirementsDiagramCanvas.generateBufferedImage throws FlowableImageException when the canvas has been closed, mirroring generateImage. Once closed, no BufferedImage can be produced from the canvas.
Solutions
- Call generateBufferedImage before close().
- Regenerate the diagram into a fresh canvas if a buffered image is needed later.
- Restructure code so all image extraction happens inside the canvas's open lifecycle.
Example fix
// before
canvas.close();
BufferedImage img = canvas.generateBufferedImage("png"); // throws
// after
BufferedImage img = canvas.generateBufferedImage("png");
canvas.close(); Defensive patterns
Strategy: type-guard
Validate before calling
if (!canvasOpen) throw new IllegalStateException("Canvas already closed; regenerate the diagram"); Type guard
boolean canRender(DefaultDecisionRequirementsDiagramCanvas c) { return c != null && !c.isClosed(); } Try / catch
try {
BufferedImage img = canvas.generateBufferedImage("png");
} catch (FlowableImageException e) {
logger.error("Canvas closed before buffered image generation", e);
} Prevention
- Extract BufferedImage before close()
- Never reuse a closed canvas
- Centralize canvas creation/closing in one code path
When it happens
Trigger: Calling generateBufferedImage(imageType) after close() was called on the same canvas instance.
Common situations: Requesting a BufferedImage after already exporting an InputStream via generateImage followed by close(); reusing a cached canvas after its lifecycle ended.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- CaseDiagramGenerator already closed
- CaseDiagramGenerator already closed
- Could not find graphic info for decision service
- Error while generating case image
- ProcessDiagramGenerator already closed
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ce7e38d09753f466.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-dmn-image-generator/src/main/java/org/flowable/dmn/image/impl/DefaultDecisionRequirementsDiagramCanvas.java:212
throw new FlowableImageException("CaseDiagramGenerator already closed");
}
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
ImageIO.write(decisionRequirementsDiagram, imageType, out);
return new ByteArrayInputStream(out.toByteArray());
} catch (IOException e) {
throw new FlowableImageException("Error while generating case image", e);
}
}
/**
* Generates an image of what currently is drawn on the canvas.
*
* Throws an {@link FlowableImageException} when {@link #close()} is already called.
*/
public BufferedImage generateBufferedImage(String imageType) {
if (closed) {
throw new FlowableImageException("DecisionRequirementsDiagramGenerator already closed");
}
// Try to remove white space
minX = (minX <= 5) ? 5 : minX;
minY = (minY <= 5) ? 5 : minY;
BufferedImage imageToSerialize = decisionRequirementsDiagram;
imageToSerialize = decisionRequirementsDiagram.getSubimage(minX - 5, minY - 5, canvasWidth - minX + 5, canvasHeight - minY + 5);
return imageToSerialize;
}
/**
* Closes the canvas which disallows further drawing and releases graphical resources.
*/
public void close() {
g.dispose();
closed = true;
}
View on GitHub (pinned to d6d39ce1c6)