{"record":{"id":"68f29756dfbd89dd","repo":"flowable/flowable-engine","slug":"attachment-content-is-required","errorCode":null,"errorMessage":"Attachment content is required.","messagePattern":"Attachment content is required\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskAttachmentCollectionResource.java","lineNumber":165,"sourceCode":"\n                if (\"name\".equalsIgnoreCase(parameterName)) {\n                    name = paramMap.get(parameterName)[0];\n\n                } else if (\"description\".equalsIgnoreCase(parameterName)) {\n                    description = paramMap.get(parameterName)[0];\n\n                } else if (\"type\".equalsIgnoreCase(parameterName)) {\n                    type = paramMap.get(parameterName)[0];\n                }\n            }\n        }\n\n        if (name == null) {\n            throw new FlowableIllegalArgumentException(\"Attachment name is required.\");\n        }\n\n        if (request.getFileMap().size() == 0) {\n            throw new FlowableIllegalArgumentException(\"Attachment content is required.\");\n        }\n\n        MultipartFile file = request.getFileMap().values().iterator().next();\n\n        if (file == null) {\n            throw new FlowableIllegalArgumentException(\"Attachment content is required.\");\n        }\n\n        try {\n            Attachment createdAttachment = taskService.createAttachment(type, task.getId(), task.getProcessInstanceId(), name, description, file.getInputStream());\n\n            return restResponseFactory.createAttachmentResponse(createdAttachment);\n\n        } catch (Exception e) {\n            throw new FlowableException(\"Error creating attachment response\", e);\n        }\n    }\n}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskAttachmentCollectionResource.java#L147-L183","documentation":"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.","triggerScenarios":"POST to /runtime/tasks/{taskId}/attachments with multipart/form-data but zero file entries in the request's file map (request.getFileMap().size() == 0).","commonSituations":"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.","solutions":["Include a file part in the multipart request, e.g. curl -F 'file=@document.pdf' -F 'name=My attachment'","Verify the client library actually sends multipart/form-data (not urlencoded or raw body)","Check no intermediary (proxy/gateway) strips the file part","Confirm the endpoint is the binary one (POST .../attachments/content) when uploading content"],"exampleFix":"// before\ncurl -X POST -F 'name=report' http://host/flowable-rest/runtime/tasks/{taskId}/attachments\n// after\ncurl -X POST -F 'name=report' -F 'file=@report.pdf' http://host/flowable-rest/runtime/tasks/{taskId}/attachments","handlingStrategy":"validation","validationCode":"const hasFile = formData.get('file') instanceof File && formData.get('file').size > 0;\nif (!hasFile) throw new Error('A non-empty file part is required for binary attachment upload');","typeGuard":"function hasFilePart(fd) { const f = fd.get('file'); return f instanceof File && f.size > 0; }","tryCatchPattern":"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; } }","preventionTips":["Always append a file part named 'file' to the multipart form","Check file.size > 0 before uploading","Use the metadata endpoint instead when no content should be stored","Test uploads with curl -F to verify the multipart encoding"],"tags":["rest","validation","multipart","attachments"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}