flowable/flowable-engine · error · ActivitiIllegalArgumentException
activity tenant id is null
Error message
activity tenant id is null
What it means
HistoricActivityInstanceQueryImpl.activityTenantId(tenantId) validates that the tenant id used as an exact-match filter is not null. Tenant filtering by equality to null is not supported, so the library fails fast with ActivitiIllegalArgumentException. Use activityTenantIdWithoutTenant() if you specifically want activities with no tenant.
Solutions
- Pass a concrete tenant id string to activityTenantId().
- If the intent is 'no tenant', call activityTenantIdWithoutTenant() instead of passing null.
- Guard the call site: only invoke the query when TenantContext.getTenantId() is non-null.
- Propagate tenant id explicitly into async/job code paths where the context is lost.
Example fix
// before
String tenant = TenantContext.getTenantId(); // may be null
query.activityTenantId(tenant);
// after
String tenant = TenantContext.getTenantId();
if (tenant != null) {
query.activityTenantId(tenant);
} else {
query.activityTenantIdWithoutTenant();
} Defensive patterns
Strategy: validation
Validate before calling
if (tenantId == null && !allowTenantless) throw new IllegalArgumentException("tenantId required for activityTenantId()"); Type guard
boolean hasTenant(String t) { return t != null && !t.isEmpty(); } Try / catch
try {
query.activityTenantId(tenantId);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("activity tenant id is null")) {
query.activityTenantIdWithoutTenant(); // fallback for tenantless data
}
} Prevention
- Use activityTenantIdWithoutTenant() for the no-tenant case.
- Propagate tenant context into async/job code paths.
- Default missing tenant config explicitly at startup.
- Reject missing tenant at your API boundary before reaching the query.
When it happens
Trigger: Calling historicActivityInstanceQuery.activityTenantId(null), typically when the tenant id comes from an unset context variable, a missing authenticated tenant, or an optional config value.
Common situations: Multi-tenant deployments where the tenant context is not populated (e.g. calling from a job or async executor without tenant context); users omitting the tenant in an API request; migrations from single-tenant setups.
Related errors
- process instance tenant id is null
- activity tenant id is null
- Business key is null
- Deployment id is null
- deploymentCategory is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/6e9f6b745d004d5a.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricActivityInstanceQueryImpl.java:131
@Override
public HistoricActivityInstanceQueryImpl finished() {
this.finished = true;
this.unfinished = false;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl unfinished() {
this.unfinished = true;
this.finished = false;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl activityTenantId(String tenantId) {
if (tenantId == null) {
throw new ActivitiIllegalArgumentException("activity tenant id is null");
}
this.tenantId = tenantId;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl activityTenantIdLike(String tenantIdLike) {
if (tenantIdLike == null) {
throw new ActivitiIllegalArgumentException("activity tenant id is null");
}
this.tenantIdLike = tenantIdLike;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl activityWithoutTenantId() {
this.withoutTenantId = true;
return this;View on GitHub (pinned to d6d39ce1c6)