flowable/flowable-engine · error · FlowableObjectNotFoundException
Task ' ' does not have an attachment with id ' '.
Error message
Task '{taskId}' does not have an attachment with id '{attachmentId}'. What it means
FlowableObjectNotFoundException thrown when fetching the content of a task attachment: either no attachment exists with the given id, or the attachment exists but belongs to a different task than the one in the URL path. The API refuses to serve content for an attachment not linked to the specified task.
Solutions
- Verify the attachmentId actually belongs to the given taskId (list via GET .../attachments first)
- Re-fetch the attachment list for the correct task and use one of those ids
- Check you are pointed at the right database/tenant/schema
- If the task is historic, use the corresponding history endpoints
Example fix
// before
GET /runtime/tasks/101/attachments/999/content // 999 belongs to task 202
// after
GET /runtime/tasks/101/attachments // pick an id from this list
GET /runtime/tasks/101/attachments/{correctId}/content Defensive patterns
Strategy: validation
Validate before calling
const att = await api.getTaskAttachment(taskId, attachmentId); // 404 here means wrong pair, don't call content
if (!att) throw new Error(`Attachment ${attachmentId} does not belong to task ${taskId}`); Try / catch
try { return await api.getAttachmentContent(taskId, attachmentId); } catch (e) { if (e.status === 404) { return null; // treat as missing
} throw e; } Prevention
- Always obtain attachmentId from the parent task's attachment list
- Never hard-code attachment ids across environments
- Re-fetch ids after task completion/cleanup
When it happens
Trigger: GET /runtime/tasks/{taskId}/attachments/{attachmentId}/content where taskService.getAttachment(attachmentId) returns null or attachment.getTaskId() != taskId.
Common situations: Copy-pasting an attachmentId from a different task; using a historic attachment id after task cleanup; tenant/datasource mismatch causing lookups against the wrong database; typos in the id.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Attachment with id ' ' does not have content associated…
- Task ' ' does not have an attachment with id ' '.
- Attachment content is required.
- Could not find a app model json with id
- Could not find a dead letter job with id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e4213b5eb4d7017f.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskAttachmentContentResource.java:60
*/
@RestController
@Api(tags = { "Task Attachments" }, authorizations = { @Authorization(value = "basicAuth") })
public class TaskAttachmentContentResource extends TaskBaseResource {
@ApiOperation(value = "Get the content for an attachment", tags = { "Task Attachments" },
notes = "The response body contains the binary content. By default, the content-type of the response is set to application/octet-stream unless the attachment type contains a valid Content-type.")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Indicates the task and attachment was found and the requested content is returned."),
@ApiResponse(code = 404, message = "Indicates the requested task was not found or the task does not have an attachment with the given id or the attachment does not have a binary stream available. Status message provides additional information.")
})
@GetMapping(value = "/runtime/tasks/{taskId}/attachments/{attachmentId}/content")
public ResponseEntity<byte[]> getAttachmentContent(@ApiParam(name = "taskId") @PathVariable("taskId") String taskId, @ApiParam(name = "attachmentId") @PathVariable("attachmentId") String attachmentId, HttpServletResponse response) {
HistoricTaskInstance task = getHistoricTaskFromRequest(taskId);
Attachment attachment = taskService.getAttachment(attachmentId);
if (attachment == null || !task.getId().equals(attachment.getTaskId())) {
throw new FlowableObjectNotFoundException("Task '" + task.getId() + "' does not have an attachment with id '" + attachmentId + "'.", Attachment.class);
}
InputStream attachmentStream = taskService.getAttachmentContent(attachmentId);
if (attachmentStream == null) {
throw new FlowableObjectNotFoundException("Attachment with id '" + attachmentId + "' does not have content associated with it.", Attachment.class);
}
HttpHeaders responseHeaders = new HttpHeaders();
MediaType mediaType = null;
if (attachment.getType() != null) {
try {
mediaType = MediaType.valueOf(attachment.getType());
responseHeaders.set("Content-Type", attachment.getType());
} catch (Exception e) {
// ignore if unknown media type
}
}
View on GitHub (pinned to d6d39ce1c6)