flowable/flowable-engine · error · FlowableIllegalArgumentException

Attachment content is required.

Error message

Attachment content is required.

What it means

Thrown by TaskAttachmentCollectionResource.createBinaryAttachment when a multipart request to create a binary task attachment contains no file part. The Flowable REST API requires uploaded content for binary attachments; name and description alone are insufficient, so the request is rejected as an illegal argument.

Solutions

  1. Include a file part in the multipart request, e.g. curl -F 'file=@document.pdf' -F 'name=My attachment'
  2. Verify the client library actually sends multipart/form-data (not urlencoded or raw body)
  3. Check no intermediary (proxy/gateway) strips the file part
  4. Confirm the endpoint is the binary one (POST .../attachments/content) when uploading content

Example fix

// before
curl -X POST -F 'name=report' http://host/flowable-rest/runtime/tasks/{taskId}/attachments
// after
curl -X POST -F 'name=report' -F 'file=@report.pdf' http://host/flowable-rest/runtime/tasks/{taskId}/attachments
Defensive patterns

Strategy: validation

Validate before calling

const hasFile = formData.get('file') instanceof File && formData.get('file').size > 0;
if (!hasFile) throw new Error('A non-empty file part is required for binary attachment upload');

Type guard

function hasFilePart(fd) { const f = fd.get('file'); return f instanceof File && f.size > 0; }

Try / catch

try { await api.createBinaryAttachment(taskId, formData); } catch (e) { if (e.status === 400 && /content is required/.test(e.message)) { alert('Attach a file before submitting'); } else { throw e; } }

Prevention

When it happens

Trigger: POST to /runtime/tasks/{taskId}/attachments with multipart/form-data but zero file entries in the request's file map (request.getFileMap().size() == 0).

Common situations: Client sends only form fields (name/description/type) without a file part; using the wrong multipart field name so the server doesn't recognize the file; testing with curl -F 'name=x' but forgetting -F 'file=@...'; a proxy stripping the file part.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/68f29756dfbd89dd. Report an issue: GitHub.

Appendix: source

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

                if ("name".equalsIgnoreCase(parameterName)) {
                    name = paramMap.get(parameterName)[0];

                } else if ("description".equalsIgnoreCase(parameterName)) {
                    description = paramMap.get(parameterName)[0];

                } else if ("type".equalsIgnoreCase(parameterName)) {
                    type = paramMap.get(parameterName)[0];
                }
            }
        }

        if (name == null) {
            throw new FlowableIllegalArgumentException("Attachment name is required.");
        }

        if (request.getFileMap().size() == 0) {
            throw new FlowableIllegalArgumentException("Attachment content is required.");
        }

        MultipartFile file = request.getFileMap().values().iterator().next();

        if (file == null) {
            throw new FlowableIllegalArgumentException("Attachment content is required.");
        }

        try {
            Attachment createdAttachment = taskService.createAttachment(type, task.getId(), task.getProcessInstanceId(), name, description, file.getInputStream());

            return restResponseFactory.createAttachmentResponse(createdAttachment);

        } catch (Exception e) {
            throw new FlowableException("Error creating attachment response", e);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)