flowable/flowable-engine · error · FlowableException

Error reading image stream

Error message

Error reading image stream

What it means

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.

Source

Thrown at modules/flowable-dmn-rest/src/main/java/org/flowable/dmn/rest/service/api/repository/DecisionImageResource.java:61

public class DecisionImageResource extends BaseDecisionResource {

    @ApiOperation(value = "Get a decision requirements diagram image", tags = { "Decisions" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates request was successful and the decision requirements diagram image returned"),
            @ApiResponse(code = 404, message = "Indicates the requested decision requirements diagram image was not found.")
    })
    @GetMapping(value = "/dmn-repository/decisions/{decisionId}/image", produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<byte[]> getImageResource(@ApiParam(name = "decisionId") @PathVariable String decisionId) {
        DmnDecision decision = getDecisionFromRequest(decisionId);
        
        try (final InputStream imageStream = dmnRepositoryService.getDecisionRequirementsDiagram(decision.getId())) {
            if (imageStream != null) {
                HttpHeaders responseHeaders = new HttpHeaders();
                responseHeaders.set("Content-Type", MediaType.IMAGE_PNG_VALUE);
                try {
                    return new ResponseEntity<>(IOUtils.toByteArray(imageStream), responseHeaders, HttpStatus.OK);
                } catch (Exception e) {
                    throw new FlowableException("Error reading image stream", e);
                }
            } else {
                throw new FlowableObjectNotFoundException("Decision with id '" + decision.getId() + "' has no image.");
            }
            
        } catch (IOException e) {
            throw new FlowableException("Error reading image stream", e);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Log the chained cause (e.getCause()) to identify the actual IO/SQL failure and retry after fixing connectivity.
  2. Ensure the deployment actually includes the diagram resource; redeploy with the image if missing (avoids the related 'has no image' error).
  3. If the image blob is corrupted, redeploy the decision resources.
  4. Increase read timeouts / heap for large diagram resources.

Example fix

// before
ResponseEntity<byte[]> img = client.getDecisionImageResource(decisionId); // FlowableException
// after
try {
    return client.getDecisionImageResource(decisionId);
} catch (FlowableObjectNotFoundException e) {
    return ResponseEntity.notFound().build(); // decision has no image
} catch (FlowableException e) {
    logger.error("image stream failed:", e.getCause());
    return retry(() -> client.getDecisionImageResource(decisionId));
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    return client.getDecisionImageResource(decisionId);
} catch (FlowableObjectNotFoundException e) {
    // 'has no image' -> treat as 404, don't retry
} catch (FlowableException e) {
    // 'Error reading image stream' -> check e.getCause(), retry if transient
}

Prevention

When it happens

Trigger: 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.)

Common situations: 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.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/22789f3341b1521e. Report an issue: GitHub.