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

  1. Verify the attachmentId actually belongs to the given taskId (list via GET .../attachments first)
  2. Re-fetch the attachment list for the correct task and use one of those ids
  3. Check you are pointed at the right database/tenant/schema
  4. 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

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


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)