flowable/flowable-engine · error · ActivitiIllegalArgumentException
processDefinition tenantId is null
Error message
processDefinition tenantId is null
What it means
ProcessDefinitionQueryImpl.processDefinitionTenantId(String) throws ActivitiIllegalArgumentException 'processDefinition tenantId is null' when the tenantId argument is null. In multi-tenant Flowable setups the tenant filter must be a concrete (possibly empty-string-means-no-tenant) value; null is rejected eagerly to keep the SQL predicate valid. This is a client-side argument contract violation.
Solutions
- Resolve the tenant id from the authenticated context before building the query; fail fast if absent
- If the intent is 'no tenant', pass the empty string "" (the engine convention) rather than null
- Make the tenant filter conditional when tenant isolation is not required
- Catch ActivitiIllegalArgumentException and return a clear 'tenant required' error
Example fix
// before
query.processDefinitionTenantId(tenantContext.currentTenantId()); // null in scheduler
// after
String tenantId = tenantContext.currentTenantId();
if (tenantId != null) {
query.processDefinitionTenantId(tenantId);
} else {
query.processDefinitionTenantIdWithoutTenant();
} Defensive patterns
Strategy: validation
Validate before calling
if (tenantId == null) throw new IllegalArgumentException("tenantId is required (use \"\" for no tenant)");
query.processDefinitionTenantId(tenantId); Type guard
boolean hasTenantContext(String t) { return t != null; } Try / catch
try {
query.processDefinitionTenantId(tenantId);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("tenantId is null")) {
throw new BadRequestException("tenant context is required for this query");
}
throw e;
} Prevention
- Resolve tenant ids from the security/tenant context and fail fast when absent
- Use processDefinitionTenantIdWithoutTenant() or "" instead of null for no-tenant queries
- Ensure background jobs propagate or re-establish tenant context
- Validate tenant headers/claims at the entry point of every request
When it happens
Trigger: Calling ProcessDefinitionQuery.processDefinitionTenantId(null) — commonly when the tenant id comes from a security context, request header, or tenant resolver that returned null (e.g. code running outside a tenant-aware context).
Common situations: Multi-tenant apps where background jobs/schedulers have no tenant context; missing X-Tenant-ID header forwarding; tenantId field absent in config or JWT claims; migrating single-tenant code into a multi-tenant deployment.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1a5864381c548dd0.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/ProcessDefinitionQueryImpl.java:256
return this;
}
@Override
public ProcessDefinitionQuery active() {
this.suspensionState = SuspensionState.ACTIVE;
return this;
}
@Override
public ProcessDefinitionQuery suspended() {
this.suspensionState = SuspensionState.SUSPENDED;
return this;
}
@Override
public ProcessDefinitionQuery processDefinitionTenantId(String tenantId) {
if (tenantId == null) {
throw new ActivitiIllegalArgumentException("processDefinition tenantId is null");
}
this.tenantId = tenantId;
return this;
}
@Override
public ProcessDefinitionQuery processDefinitionTenantIdLike(String tenantIdLike) {
if (tenantIdLike == null) {
throw new ActivitiIllegalArgumentException("process definition tenantId is null");
}
this.tenantIdLike = tenantIdLike;
return this;
}
@Override
public ProcessDefinitionQuery processDefinitionWithoutTenantId() {
this.withoutTenantId = true;
return this;View on GitHub (pinned to d6d39ce1c6)