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
- Inspect the 'cause' exception in the server log to find the underlying I/O/DB error.
- Re-upload the user's picture via PUT identity/users/{userId}/picture to replace the corrupt/missing blob.
- Verify database connectivity and that the byte-array storage (e.g. ACT_GE_BYTEARRAY) is intact; restore from backup if rows were purged.
- 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
- Never manually purge ACT_GE_BYTEARRAY rows without updating user references.
- Monitor DB connectivity/pool health for the Flowable datasource.
- Inspect the exception cause in server logs to separate transient IO errors from corrupt blobs.
- Re-upload pictures after database restores or migrations.
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
- The user with id ' ' does not have a picture.
- A group or a user is required to create an identity link.
- A group or a user is required to create an identity link.
- Authentication failed for this username and password
- Comment text is required.
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)