{"record":{"id":"906e6a315dbb101c","repo":"flowable/flowable-engine","slug":"html-or-text-is-required-to-be-defined-when-us","errorCode":null,"errorMessage":"'html' or 'text' is required to be defined when using the mail activity","messagePattern":"'html' or 'text' is required to be defined when using the mail activity","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/mail/BaseMailActivityDelegate.java","lineNumber":113,"sourceCode":"        Collection<String> toList = parseRecipients(to, variableContainer);\n        String fromStr = getStringFromField(from, variableContainer);\n        Collection<String> ccList = parseRecipients(cc, variableContainer);\n        Collection<String> bccList = parseRecipients(bcc, variableContainer);\n        String subjectStr = getStringFromField(subject, variableContainer);\n        String textStr = textVar == null ?\n                getStringFromField(text, variableContainer) :\n                getStringFromField(getExpression(variableContainer, textVar), variableContainer);\n        String htmlStr = htmlVar == null ?\n                getStringFromField(html, variableContainer) :\n                getStringFromField(getExpression(variableContainer, htmlVar), variableContainer);\n        String charSetStr = getStringFromField(charset, variableContainer);\n\n        if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty()) {\n            throw new FlowableException(\"No recipient could be found for sending email for \" + variableContainer);\n        }\n\n        if (htmlStr == null && textStr == null) {\n            throw new FlowableIllegalArgumentException(\"'html' or 'text' is required to be defined when using the mail activity\");\n        }\n\n        MailMessage message = new MailMessage();\n\n        addHeader(message, headersStr);\n        message.setTo(toList);\n        message.setFrom(fromStr);\n        message.setCc(ccList);\n        message.setBcc(bccList);\n        message.setSubject(subjectStr);\n        message.setPlainContent(textStr);\n        message.setHtmlContent(htmlStr);\n        if (charSetStr != null) {\n            message.setCharset(Charset.forName(charSetStr));\n        }\n        addAttachments(message, variableContainer);\n\n        return message;","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/mail/BaseMailActivityDelegate.java#L95-L131","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the 'html' field (or 'text' field) on the mail activity, e.g. <flowable:field name=\"html\"><flowable:expression>...</flowable:expression></flowable:field>","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'}","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"],"exampleFix":"// before\n<serviceTask id=\"sendMail\" flowable:type=\"mail\">\n  <extensionElements>\n    <flowable:field name=\"to\" expression=\"${user.email}\"/>\n  </extensionElements>\n</serviceTask>\n// after\n<serviceTask id=\"sendMail\" flowable:type=\"mail\">\n  <extensionElements>\n    <flowable:field name=\"to\" expression=\"${user.email}\"/>\n    <flowable:field name=\"subject\" expression=\"Notification\"/>\n    <flowable:field name=\"html\">\n      <flowable:expression><![CDATA[${emailBody}]]></flowable:expression>\n    </flowable:field>\n  </extensionElements>\n</serviceTask>","handlingStrategy":"validation","validationCode":"String html = resolveHtml(); String text = resolveText();\nif (html == null && text == null) {\n    throw new IllegalArgumentException(\"Mail task requires 'html' or 'text' to be set\");\n}","typeGuard":"boolean hasMailBody(String html, String text) { return html != null || text != null; }","tryCatchPattern":"try {\n    // execute mail task / delegate\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"'html' or 'text' is required\")) {\n        // fix process definition: add body field\n    }\n    throw e;\n}","preventionTips":["Always configure html or text on every mail task","Validate BPMN mail tasks at deployment time with a custom validator","Default expressions to empty strings instead of null for optional bodies"],"tags":["email","validation","bpmn"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}