{"record":{"id":"22789f3341b1521e","repo":"flowable/flowable-engine","slug":"error-reading-image-stream-22789f","errorCode":null,"errorMessage":"Error reading image stream","messagePattern":"Error reading image stream","errorType":"http","errorClass":"FlowableException","httpStatus":500,"severity":"error","filePath":"modules/flowable-dmn-rest/src/main/java/org/flowable/dmn/rest/service/api/repository/DecisionImageResource.java","lineNumber":61,"sourceCode":"public class DecisionImageResource extends BaseDecisionResource {\n\n    @ApiOperation(value = \"Get a decision requirements diagram image\", tags = { \"Decisions\" })\n    @ApiResponses(value = {\n            @ApiResponse(code = 200, message = \"Indicates request was successful and the decision requirements diagram image returned\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested decision requirements diagram image was not found.\")\n    })\n    @GetMapping(value = \"/dmn-repository/decisions/{decisionId}/image\", produces = MediaType.IMAGE_PNG_VALUE)\n    public ResponseEntity<byte[]> getImageResource(@ApiParam(name = \"decisionId\") @PathVariable String decisionId) {\n        DmnDecision decision = getDecisionFromRequest(decisionId);\n        \n        try (final InputStream imageStream = dmnRepositoryService.getDecisionRequirementsDiagram(decision.getId())) {\n            if (imageStream != null) {\n                HttpHeaders responseHeaders = new HttpHeaders();\n                responseHeaders.set(\"Content-Type\", MediaType.IMAGE_PNG_VALUE);\n                try {\n                    return new ResponseEntity<>(IOUtils.toByteArray(imageStream), responseHeaders, HttpStatus.OK);\n                } catch (Exception e) {\n                    throw new FlowableException(\"Error reading image stream\", e);\n                }\n            } else {\n                throw new FlowableObjectNotFoundException(\"Decision with id '\" + decision.getId() + \"' has no image.\");\n            }\n            \n        } catch (IOException e) {\n            throw new FlowableException(\"Error reading image stream\", e);\n        }\n    }\n}\n","sourceCodeStart":43,"sourceCodeEnd":72,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-rest/src/main/java/org/flowable/dmn/rest/service/api/repository/DecisionImageResource.java#L43-L72","documentation":"DecisionImageResource.getImageResource reads the diagram image for a decision; when the image stream is non-null it converts it with IOUtils.toByteArray, and any exception there is wrapped as FlowableException(\"Error reading image stream\", e). A companion FlowableObjectNotFoundException is thrown when the decision simply has no image. This error means the image exists but its bytes could not be read/converted.","triggerScenarios":"GET of a decision's image resource where IOUtils.toByteArray(imageStream) throws: broken or closed stream from the repository service, database blob read failure, or IOException during conversion. (If the decision has no diagram, the separate 'has no image' FlowableObjectNotFoundException is thrown instead.)","commonSituations":"DMN resources deployed without diagram resources (callers hitting the no-image 404 path); DB connectivity issues or corrupted image blobs; truncation/timeout reading large PNG resources; upgrading engines where diagram generation settings changed.","solutions":["Log the chained cause (e.getCause()) to identify the actual IO/SQL failure and retry after fixing connectivity.","Ensure the deployment actually includes the diagram resource; redeploy with the image if missing (avoids the related 'has no image' error).","If the image blob is corrupted, redeploy the decision resources.","Increase read timeouts / heap for large diagram resources."],"exampleFix":"// before\nResponseEntity<byte[]> img = client.getDecisionImageResource(decisionId); // FlowableException\n// after\ntry {\n    return client.getDecisionImageResource(decisionId);\n} catch (FlowableObjectNotFoundException e) {\n    return ResponseEntity.notFound().build(); // decision has no image\n} catch (FlowableException e) {\n    logger.error(\"image stream failed:\", e.getCause());\n    return retry(() -> client.getDecisionImageResource(decisionId));\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return client.getDecisionImageResource(decisionId);\n} catch (FlowableObjectNotFoundException e) {\n    // 'has no image' -> treat as 404, don't retry\n} catch (FlowableException e) {\n    // 'Error reading image stream' -> check e.getCause(), retry if transient\n}","preventionTips":["Deploy DMN models together with their diagram resources so images always exist","Distinguish the no-image not-found from the stream-read failure by exception type","Monitor DB health; log wrapped causes for blob read errors","Allow adequate timeouts/heap for large diagram resources"],"tags":["io","image","stream"],"backgroundTag":"file-read-failed","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}