flowable/flowable-engine · error · FlowableException

no SMTP host is configured for the mail server for tenant {t

Error message

no SMTP host is configured for the mail server for tenant {tenantId}

What it means

When building per-tenant mail clients, Flowable validates that each tenant's configured MailServerInfo has a host. If a tenant-specific mail server was registered without a host, it throws this FlowableException naming the tenant. This prevents tenant-scoped mail activities from failing later at send time.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/ProcessEngineConfigurationImpl.java:2410

        Collection<String> tenantIds = new HashSet<>(mailSessionsJndi.keySet());
        tenantIds.addAll(mailServers.keySet());

        if (!tenantIds.isEmpty()) {
            Map<String, FlowableMailClient> mailClients = defaultMailClientProvider.getMailClients();
            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));
                }
            }
        }
    }

    public 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)

Solutions

  1. Set the host for the affected tenant: config.addTenantMailServer(tenantId, mailServerInfo) with mailServerInfo.setMailServerHost("smtp.example.com").
  2. Fix the tenant mail server entry in your properties/database so host is non-empty for every tenant id.
  3. Remove the tenant entry entirely if that tenant has no mail server and the default server should apply.

Example fix

// before
MailServerInfo tenantServer = new MailServerInfo();
config.addTenantMailServer("tenant-a", tenantServer);
// after
MailServerInfo tenantServer = new MailServerInfo();
tenantServer.setMailServerHost("smtp.tenant-a.com");
config.addTenantMailServer("tenant-a", tenantServer);
Defensive patterns

Strategy: validation

Validate before calling

mailServers.forEach((tenantId, info) -> {
    if (info.getMailServerHost() == null || info.getMailServerHost().isBlank()) {
        throw new IllegalStateException("Mail server host missing for tenant " + tenantId);
    }
});

Prevention

When it happens

Trigger: During ProcessEngineConfigurationImpl initialization, iterating mailServers: a tenant id key exists in mailServers (or mailSessionsJndi mapping) whose tenantMailServer.getMailServerHost() is null.

Common situations: Multi-tenant deployments where addTenantMailServer(tenantId, ...) was called with a MailServerInfo lacking a host; tenant config loaded from a database/properties file with an empty host column; copy-paste of tenant config with only credentials set.

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


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