flowable/flowable-engine · error · FlowableObjectNotFoundException

Attachment with id ' ' does not have content associated…

Error message

Attachment with id '{attachmentId}' does not have content associated with it.

What it means

FlowableObjectNotFoundException thrown when an attachment exists and belongs to the task, but taskService.getAttachmentContent returns null — i.e. the attachment metadata exists without associated binary content. Attachments can be created with metadata only (name/description/url), so content retrieval legitimately finds nothing.

Solutions

  1. Use the attachment's externalUrl (if present) instead of fetching content
  2. Create the attachment via the binary endpoint so content is stored
  3. Check the content store configuration and whether content was purged
  4. After upgrades, verify content-store data was migrated

Example fix

// before
POST /runtime/tasks/{id}/attachments  {"name":"x","url":"http://..."}  // metadata only
GET  /runtime/tasks/{id}/attachments/{attId}/content  // 404 no content
// after
POST /runtime/tasks/{id}/attachments  -F 'file=@doc.pdf'  // binary upload
GET  /runtime/tasks/{id}/attachments/{attId}/content
Defensive patterns

Strategy: fallback

Validate before calling

const att = await api.getTaskAttachment(taskId, attachmentId);
if (att.url) { window.open(att.url); return; } // metadata-only attachment has externalUrl

Type guard

function hasExternalContent(att) { return typeof att.url === 'string' && att.url.length > 0; }

Try / catch

try { return await api.getAttachmentContent(taskId, attachmentId); } catch (e) { if (e.status === 404) { window.open(att.url || '/no-content'); return null; } throw e; }

Prevention

When it happens

Trigger: GET .../attachments/{attachmentId}/content on an attachment created without content (metadata/url-only attachment), or whose stored content was removed by cleanup/archival.

Common situations: Attachments created via the non-binary endpoint that only carry an external URL; content store purged or not migrated after a version upgrade; attachment persisted to a content store later cleared.

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/69b601666035dcb8. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskAttachmentContentResource.java:65

    @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
            }
        }

        if (mediaType == null) {
            responseHeaders.set("Content-Type", "application/octet-stream");
        }

        try {

View on GitHub (pinned to d6d39ce1c6)