flowable/flowable-engine · error · FlowableException

Error exporting picture

Error message

Error exporting picture: ${e.getMessage()}

What it means

FlowableException (generic runtime) thrown by getUserPicture when reading the picture bytes fails: IOUtils.toByteArray(userPicture.getInputStream()) raised an exception. The original exception is attached as the cause, and its message is appended to 'Error exporting picture: '. Unlike the not-found case, this indicates a problem retrieving/streaming stored picture data, e.g. an unreadable or corrupt blob.

Solutions

  1. Inspect the 'cause' exception in the server log to find the underlying I/O/DB error.
  2. Re-upload the user's picture via PUT identity/users/{userId}/picture to replace the corrupt/missing blob.
  3. Verify database connectivity and that the byte-array storage (e.g. ACT_GE_BYTEARRAY) is intact; restore from backup if rows were purged.
  4. Retry the request if the cause was a transient connection failure; check DB connection-pool health.

Example fix

// server-side: refresh the broken picture
// before: picture row missing/corrupt -> 500 Error exporting picture
// after
PUT /identity/users/jdoe/picture  (multipart/form-data)
file=@avatar.png
// re-upload replaces the blob and GET .../picture succeeds
Defensive patterns

Strategy: retry

Validate before calling

// cannot pre-validate server-side blob integrity; retry on 5xx:
const res = await fetch(url);
if (res.status >= 500) retryWithBackoff(3);

Try / catch

try {
  const res = await fetch(`/identity/users/${userId}/picture`);
  if (!res.ok) {
    const msg = await res.text();
    if (msg.includes('Error exporting picture')) {
      // check server log cause; retry once for transient DB/IO errors,
      // otherwise re-upload the picture (PUT .../picture)
    }
  }
} catch (e) { /* network error */ }

Prevention

When it happens

Trigger: The picture exists but its InputStream cannot be read — blob missing from the underlying store (DB table ACT_GE_BYTEARRAY row gone), DB connection dropped mid-stream, corrupt/zero-length blob, or an I/O error reading the stream.

Common situations: Database maintenance/manually purged byte-array rows while user references remain; datasource or network failures between the REST app and the DB; partially failed picture uploads; custom IdentityService implementations whose getUserPicture returns a Picture backed by an unavailable stream.

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/9ffdf3580c5606e4. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/identity/UserPictureResource.java:79

    public ResponseEntity<byte[]> getUserPicture(@ApiParam(name = "userId") @PathVariable String userId) {
        User user = getUserFromRequest(userId);
        Picture userPicture = identityService.getUserPicture(user.getId());

        if (userPicture == null) {
            throw new FlowableObjectNotFoundException("The user with id '" + user.getId() + "' does not have a picture.", Picture.class);
        }

        HttpHeaders responseHeaders = new HttpHeaders();
        if (userPicture.getMimeType() != null) {
            responseHeaders.set("Content-Type", userPicture.getMimeType());
        } else {
            responseHeaders.set("Content-Type", "image/jpeg");
        }

        try {
            return new ResponseEntity<>(IOUtils.toByteArray(userPicture.getInputStream()), responseHeaders, HttpStatus.OK);
        } catch (Exception e) {
            throw new FlowableException("Error exporting picture: " + e.getMessage(), e);
        }
    }

    @ApiOperation(consumes = "multipart/form-data", value = "Updating a user’s picture", tags = {
            "Users" },  notes = "The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the picture. On top of that, the following additional form-fields can be present:\n"
                    + "\n"
                    + "mimeType: Optional mime-type for the uploaded picture. If omitted, the default of image/jpeg is used as a mime-type for the picture.",
            code = 204)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", dataType = "file", value = "Picture to update", paramType = "form", required = true)
    })
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the user was found and the picture has been updated. The response-body is left empty intentionally."),
            @ApiResponse(code = 404, message = "Indicates the requested user was not found.")
    })
    @PutMapping(value = "/identity/users/{userId}/picture", consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void updateUserPicture(@ApiParam(name = "userId") @PathVariable String userId, HttpServletRequest request) {

View on GitHub (pinned to d6d39ce1c6)