flowable/flowable-engine · error · FlowableException
Invalid attachment type: " + value.getClass() + " for " +…
Error message
Invalid attachment type: " + value.getClass() + " for " + variableContainer
What it means
Mail attachments supplied via the 'attachments' expression must be of a supported type (String file path, File, ContentItem, or ContentItem[]). addExpressionValueAttachment throws FlowableException when the attachment expression resolves to any other class. The message includes the offending value's class to aid diagnosis.
Solutions
- Convert the attachment value to the supported types: String path, java.io.File, ContentItem, or ContentItem[]
- If you have a List<ContentItem>, convert with list.toArray(new ContentItem[0]) before assigning
- Store binary content as a ContentItem via the content engine rather than byte[] when using mail attachments
Example fix
// before
execution.setVariable("attachments", contentItemList); // List<ContentItem>
// after
execution.setVariable("attachments", contentItemList.toArray(new ContentItem[0])); Defensive patterns
Strategy: type-guard
Validate before calling
Object att = execution.getVariable("attachments");
boolean ok = att instanceof String || att instanceof java.io.File
|| att instanceof ContentItem || att instanceof ContentItem[];
if (!ok) throw new IllegalArgumentException("Unsupported attachment type: " + att.getClass()); Type guard
boolean isSupportedAttachment(Object v) {
return v instanceof String || v instanceof java.io.File
|| v instanceof ContentItem || v instanceof ContentItem[];
} Try / catch
try {
// mail task with attachments
} catch (FlowableException e) {
if (e.getMessage().startsWith("Invalid attachment type")) {
// convert variable to ContentItem[] before retrying
}
throw e;
} Prevention
- Store attachments as ContentItem or ContentItem[] process variables
- Convert List<ContentItem> to arrays before assigning
- Avoid byte[]/InputStream variables for mail attachments
When it happens
Trigger: The attachments field expression evaluates to an unsupported type, e.g. a byte[], an InputStream, a List<ContentItem> (not an array), a POJO, or a Collection returned by an expression.
Common situations: Passing a java.util.List or List of ContentItem from a variable instead of a ContentItem[] array; passing raw byte[] of file data; passing the wrong variable from a previous service task.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- App resource is not of type AppModel
- Attachment content is required.
- Attachment name is required.
- Attachment with id ' ' does not have content associated…
- AttachmentRequest properties not found in request
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/31997165763af01e.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/mail/BaseMailActivityDelegate.java:209
} else if (value instanceof DataSource dataSource) {
message.addAttachment(dataSource);
} else if (value instanceof DataSource[] dataSources) {
for (DataSource dataSource : dataSources) {
addExpressionValueAttachment(message, dataSource, variableContainer);
}
} else if (value instanceof ContentItem contentItem) {
message.addAttachment(new ContentItemDataSourceWrapper(contentItem, getContentService()));
} else if (value instanceof ContentItem[] contentItems) {
for (ContentItem contentItem : contentItems) {
addExpressionValueAttachment(message, contentItem, variableContainer);
}
} else {
throw new FlowableException("Invalid attachment type: " + value.getClass() + " for " + variableContainer);
}
}
protected String getStringFromField(Expression expression, V variableContainer) {
if (expression != null) {
Object value = expression.getValue(variableContainer);
if (value != null) {
return value.toString();
}
}
return null;
}
protected Collection<String> parseRecipients(Expression expression, V variableContainer) {
if (expression == null) {
return Collections.emptyList();
}View on GitHub (pinned to d6d39ce1c6)