flowable/flowable-engine · error · FlowableException
no SMTP host is configured for the mail server for tenant
Error message
no SMTP host is configured for the mail server for tenant ${tenantId} What it means
When initializing per-tenant mail clients, Flowable iterates the configured tenant mail servers and builds a client for each. If a tenant's MailServerInfo has a null host (and no JNDI session applies), the engine cannot create an SMTP client for that tenant and throws this FlowableException naming the tenantId.
Solutions
- Set the host for the offending tenant: config.addMailServer(tenantId, new MailServerInfo(... host="smtp.tenant.com" ...)) or setMailServerHost equivalent per tenant
- Configure a JNDI mail session for the tenant via mailSessionsJndi so host lookup is bypassed
- Audit the tenant mail server map before building the engine and log/fail fast on entries missing a host
- Fall back to the default mail server by removing the incomplete tenant entry if the tenant should use default SMTP settings
Example fix
// before
MailServerInfo info = new MailServerInfo();
info.setMailServerUser("user");
config.addMailServer("tenantA", info);
// after
MailServerInfo info = new MailServerInfo();
info.setMailServerHost("smtp.tenant-a.com");
info.setMailServerUser("user");
config.addMailServer("tenantA", info); Defensive patterns
Strategy: validation
Validate before calling
for (Map.Entry<String, MailServerInfo> e : config.getMailServers().entrySet()) {
MailServerInfo info = e.getValue();
if (info == null || info.getMailServerHost() == null || info.getMailServerHost().isEmpty()) {
throw new IllegalStateException("Mail server host missing for tenant " + e.getKey());
}
} Prevention
- Validate every tenant MailServerInfo has a host right after building the tenant config map
- Centralize tenant mail config construction so defaults (including host) are always applied
- Cover tenant mail configuration with a startup smoke test in multi-tenant environments
- Fall back deliberately: decide whether incomplete tenants should inherit the default mail server instead of being registered with a null host
When it happens
Trigger: Calling buildProcessEngine() with mailServers populated (via setMailServers/addMailServer) where the MailServerInfo for a specific tenantId has mailServerHost == null and no mail session JNDI is configured for that tenant.
Common situations: Multi-tenant deployments where one tenant's entry was added with only user/password/port but no host; a tenant properties map missing the host key; programmatic config that copies defaults but leaves host null.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Could not send email: no SMTP host is configured
- no SMTP host is configured for the default mail server
- no SMTP host is configured for the default mail server
- no SMTP host is configured for the default mail server
- no SMTP host is configured for the mail server for tenant
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e34962ad71e3f342.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java:1487
}
Collection<String> tenantIds = new HashSet<>(mailSessionsJndi.keySet());
tenantIds.addAll(mailServers.keySet());
if (!tenantIds.isEmpty()) {
MailServerInfo defaultMailServer = getDefaultMailServer();
for (String tenantId : tenantIds) {
if (mailClients.containsKey(tenantId)) {
continue;
}
String sessionJndi = mailSessionsJndi.get(tenantId);
MailServerInfo tenantMailServer = mailServers.get(tenantId);
if (sessionJndi != null) {
mailClients.put(tenantId, FlowableMailClientCreator.createSessionClient(sessionJndi, tenantMailServer, defaultMailServer));
} else if (tenantMailServer != null) {
String host = tenantMailServer.getMailServerHost();
if (host == null) {
throw new FlowableException("no SMTP host is configured for the mail server for tenant " + tenantId);
}
mailClients.put(tenantId, FlowableMailClientCreator.createHostClient(host, tenantMailServer, defaultMailServer));
}
}
}
}
protected void initBusinessCalendarManager() {
if (businessCalendarManager == null) {
MapBusinessCalendarManager mapBusinessCalendarManager = new MapBusinessCalendarManager();
mapBusinessCalendarManager.addBusinessCalendar(DurationBusinessCalendar.NAME, new DurationBusinessCalendar(this.clock));
mapBusinessCalendarManager.addBusinessCalendar(DueDateBusinessCalendar.NAME, new DueDateBusinessCalendar(this.clock));
mapBusinessCalendarManager.addBusinessCalendar(CycleBusinessCalendar.NAME, new CycleBusinessCalendar(this.clock));
businessCalendarManager = mapBusinessCalendarManager;
}
}
View on GitHub (pinned to d6d39ce1c6)