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
- Filter out entries with null/empty keys from the headers map before building the SendMailRequest.
- Fix the upstream data source so header names are always present and trimmed.
- 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
- Trim and validate header names when building them from external data.
- Reject empty header names at the parse/ingestion layer.
- Add unit tests covering blank header names.
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
- header value cannot be null or empty
- Failed to create mime message
- Could not add as recipient
- Invalid email
- Could not set as from address in email
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/59c1f972aee056d4.
Report an issue: GitHub.