flowable/flowable-engine · error · FlowableMailException

header name cannot be null or empty

Error message

header name cannot be null or empty

What it means

When building the MimeMessage, addHeaders iterates the request's custom headers map and rejects any entry whose key is null or empty, throwing FlowableMailException. RFC 822 messages cannot have a header without a name, so the client fails fast instead of producing a corrupt message.

Source

Thrown at modules/flowable-mail/src/main/java/org/flowable/mail/common/impl/jakarta/mail/JakartaMailFlowableMailClient.java:151

    protected void setSubject(MimeMessage message, String subject, Charset charset) throws MessagingException {
        if (StringUtils.isNotEmpty(subject)) {
            if (charset != null) {
                message.setSubject(subject, charset.name());
            } else {
                message.setSubject(subject);
            }
        }
    }

    protected void addHeaders(MimeMessage message, Map<String, String> headers, Charset charset) throws MessagingException {
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {

                String name = entry.getKey();
                String value = entry.getValue();

                if (StringUtils.isEmpty(name)) {
                    throw new FlowableMailException("header name cannot be null or empty");
                }

                if (StringUtils.isEmpty(value)) {
                    throw new FlowableMailException("header value cannot be null or empty");
                }

                String foldedHeaderValue = createFoldedHeaderValue(name, value, charset);
                message.addHeader(name, foldedHeaderValue);
            }
        }

    }

    protected String createFoldedHeaderValue(String name, String value, Charset charset) {
        try {
            return MimeUtility.fold(name.length() + 2, MimeUtility.encodeText(value, charset != null ? charset.name() : null, null));
        } catch (UnsupportedEncodingException e) {
            return value;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Filter out entries with null/empty keys from the headers map before building the SendMailRequest.
  2. Fix the upstream data source so header names are always present and trimmed.
  3. Add application-level validation of the headers map before invoking the mail client.

Example fix

// before
Map<String,String> headers = parseHeaders(input); // may contain ""
SendMailRequest req = SendMailRequest.builder().extraHeaders(headers).build();

// after
Map<String,String> headers = parseHeaders(input).entrySet().stream()
    .filter(e -> e.getKey() != null && !e.getKey().isBlank())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Defensive patterns

Strategy: validation

Validate before calling

Map<String,String> safeHeaders = headers.entrySet().stream()
    .filter(e -> e.getKey() != null && !e.getKey().trim().isEmpty())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Type guard

boolean hasNamedHeaders(Map<String,String> h) { return h.keySet().stream().allMatch(k -> k != null && !k.isBlank()); }

Try / catch

try { client.sendMail(request); } catch (FlowableMailException e) { if (e.getMessage().contains("header name")) { log.warn("dropping request with unnamed header"); } throw e; }

Prevention

When it happens

Trigger: Passing a SendMailRequest whose extraHeaders map contains an empty-string or null key, e.g. headers built programmatically from name/value pairs where the name part was missing.

Common situations: Dynamic header construction from CSV/database rows with blank column names; parsing 'Name: Value' strings with a split that yields an empty name; deserialization of user-supplied header maps.

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/59c1f972aee056d4. Report an issue: GitHub.