flowable/flowable-engine · error · FlowableIllegalArgumentException

'html' or 'text' is required to be defined when using the ma

Error message

'html' or 'text' is required to be defined when using the mail activity

What it means

The Flowable mail activity (mail task) requires email body content, given via the 'html' or 'text' field expressions. BaseMailActivityDelegate.createMessage throws FlowableIllegalArgumentException when both are null because an email without a body cannot be sent. It enforces that at least one body representation is configured on the mail activity.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/mail/BaseMailActivityDelegate.java:113

        Collection<String> toList = parseRecipients(to, variableContainer);
        String fromStr = getStringFromField(from, variableContainer);
        Collection<String> ccList = parseRecipients(cc, variableContainer);
        Collection<String> bccList = parseRecipients(bcc, variableContainer);
        String subjectStr = getStringFromField(subject, variableContainer);
        String textStr = textVar == null ?
                getStringFromField(text, variableContainer) :
                getStringFromField(getExpression(variableContainer, textVar), variableContainer);
        String htmlStr = htmlVar == null ?
                getStringFromField(html, variableContainer) :
                getStringFromField(getExpression(variableContainer, htmlVar), variableContainer);
        String charSetStr = getStringFromField(charset, variableContainer);

        if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()) {
            throw new FlowableException("No recipient could be found for sending email for " + variableContainer);
        }

        if (htmlStr == null && textStr == null) {
            throw new FlowableIllegalArgumentException("'html' or 'text' is required to be defined when using the mail activity");
        }

        MailMessage message = new MailMessage();

        addHeader(message, headersStr);
        message.setTo(toList);
        message.setFrom(fromStr);
        message.setCc(ccList);
        message.setBcc(bccList);
        message.setSubject(subjectStr);
        message.setPlainContent(textStr);
        message.setHtmlContent(htmlStr);
        if (charSetStr != null) {
            message.setCharset(Charset.forName(charSetStr));
        }
        addAttachments(message, variableContainer);

        return message;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set the 'html' field (or 'text' field) on the mail activity, e.g. <flowable:field name="html"><flowable:expression>...</flowable:expression></flowable:field>
  2. If the body is dynamic, ensure the referenced process variable is set before the mail task executes, or provide a default via expression like ${emailBody != null ? emailBody : 'default'}
  3. Add a validation/guard in the process (e.g. a script task or exclusive gateway) that fails fast with a clear message when body variables are missing

Example fix

// before
<serviceTask id="sendMail" flowable:type="mail">
  <extensionElements>
    <flowable:field name="to" expression="${user.email}"/>
  </extensionElements>
</serviceTask>
// after
<serviceTask id="sendMail" flowable:type="mail">
  <extensionElements>
    <flowable:field name="to" expression="${user.email}"/>
    <flowable:field name="subject" expression="Notification"/>
    <flowable:field name="html">
      <flowable:expression><![CDATA[${emailBody}]]></flowable:expression>
    </flowable:field>
  </extensionElements>
</serviceTask>
Defensive patterns

Strategy: validation

Validate before calling

String html = resolveHtml(); String text = resolveText();
if (html == null && text == null) {
    throw new IllegalArgumentException("Mail task requires 'html' or 'text' to be set");
}

Type guard

boolean hasMailBody(String html, String text) { return html != null || text != null; }

Try / catch

try {
    // execute mail task / delegate
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("'html' or 'text' is required")) {
        // fix process definition: add body field
    }
    throw e;
}

Prevention

When it happens

Trigger: A mail task / mail activity is executed where neither the 'html' field nor the 'text' field resolves to a non-null string, e.g. both fields omitted from the task definition or both expressions evaluating to null at runtime.

Common situations: Modeler mistakes when creating a mail task (author sets only recipients/subject, forgets body); expressions like ${content} that evaluate to null because the process variable was never set; migrations/copies of BPMN XML where html/text elements were dropped.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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