flowable/flowable-engine · error · ActivitiIllegalArgumentException
process instance tenant id is null
Error message
process instance tenant id is null
What it means
HistoricProcessInstanceQuery.processInstanceTenantId(tenantId) validates that the exact-match tenant filter is non-null. Filtering historic process instances by a null tenant is unsupported, so the library throws ActivitiIllegalArgumentException immediately when building the query. Use processInstanceTenantIdWithoutTenant() for tenantless instances.
Solutions
- Pass an actual tenant id string.
- Use processInstanceTenantIdWithoutTenant() when you mean 'instances with no tenant'.
- Resolve the tenant before query building and fail with your own error if absent (e.g. throw IllegalArgumentException naming the missing header).
- Propagate tenant context into async executions and scheduled jobs explicitly.
Example fix
// before
query.processInstanceTenantId(secureHeader("X-Tenant")); // null if header absent
// after
String tenant = secureHeader("X-Tenant");
if (tenant == null) {
throw new MissingTenantException("X-Tenant header required");
}
query.processInstanceTenantId(tenant); Defensive patterns
Strategy: validation
Validate before calling
if (tenantId == null) throw new MissingTenantException("tenant id required for processInstanceTenantId()"); Type guard
boolean hasTenant(String t) { return t != null && !t.isEmpty(); } Try / catch
try {
query.processInstanceTenantId(tenantId);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("tenant id is null")) {
query.processInstanceTenantIdWithoutTenant();
}
} Prevention
- Resolve tenant before building any query; fail fast with a descriptive error.
- Use processInstanceTenantIdWithoutTenant() for tenantless instances.
- Ensure schedulers/async executors receive tenant context.
- Validate the tenant request header at the API edge.
When it happens
Trigger: Calling processInstanceTenantId(null) — usually a tenant variable resolved from an unauthenticated context, an unset process variable, or a missing request header.
Common situations: Multi-tenant apps where background jobs/schedulers run without tenant context; API consumers omitting the tenant header; code migrated from single-tenant versions that now passes null.
Related errors
- activity 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/16eb4715b70d4d44.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricProcessInstanceQueryImpl.java:368
public HistoricProcessInstanceQuery limitProcessInstanceVariables(Integer processInstanceVariablesLimit) {
this.processInstanceVariablesLimit = processInstanceVariablesLimit;
return this;
}
public Integer getProcessInstanceVariablesLimit() {
return processInstanceVariablesLimit;
}
@Override
public HistoricProcessInstanceQuery withJobException() {
this.withJobException = true;
return this;
}
@Override
public HistoricProcessInstanceQuery processInstanceTenantId(String tenantId) {
if (tenantId == null) {
throw new ActivitiIllegalArgumentException("process instance tenant id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.tenantId = tenantId;
} else {
this.tenantId = tenantId;
}
return this;
}
@Override
public HistoricProcessInstanceQuery processInstanceTenantIdLike(String tenantIdLike) {
if (tenantIdLike == null) {
throw new ActivitiIllegalArgumentException("process instance tenant id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.tenantIdLike = tenantIdLike;
} else {
this.tenantIdLike = tenantIdLike;View on GitHub (pinned to d6d39ce1c6)