flowable/flowable-engine · error · FlowableIllegalArgumentException
task tenant id is null
Error message
task tenant id is null
What it means
taskTenantId(String) throws FlowableIllegalArgumentException when the tenantId argument is null. Flowable requires an explicit non-null tenant id string for tenant-scoped queries; use taskWithoutTenantId() or omit the filter to match tasks without a tenant.
Source
Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:1984
this.involvedGroups = involvedGroups;
}
return this;
}
@Override
public HistoricTaskInstanceQuery ignoreAssigneeValue() {
if (inOrStatement) {
this.currentOrQueryObject.ignoreAssigneeValue = true;
} else {
this.ignoreAssigneeValue = true;
}
return this;
}
@Override
public HistoricTaskInstanceQuery taskTenantId(String tenantId) {
if (tenantId == null) {
throw new FlowableIllegalArgumentException("task tenant id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.tenantId = tenantId;
} else {
this.tenantId = tenantId;
}
return this;
}
@Override
public HistoricTaskInstanceQuery taskTenantIdLike(String tenantIdLike) {
if (tenantIdLike == null) {
throw new FlowableIllegalArgumentException("task tenant id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.tenantIdLike = tenantIdLike;
} else {
this.tenantIdLike = tenantIdLike;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Pass a non-null tenant id; resolve/validate the tenant from the request context first.
- To query tasks with no tenant, use taskWithoutTenantId() instead of passing null.
- If tenant filtering is optional, call taskTenantId() only when a tenant id is present.
- Note Flowable stores missing tenants as empty string (""); pass "" if you intentionally filter that value, or prefer taskWithoutTenantId().
Example fix
// before
query.taskTenantId(tenantContext.getTenantId()); // throws when null
// after
String tenantId = tenantContext.getTenantId();
if (tenantId != null) {
query.taskTenantId(tenantId);
} else {
query.taskWithoutTenantId();
} Defensive patterns
Strategy: validation
Validate before calling
if (tenantId != null && !tenantId.isEmpty()) {
historicTaskInstanceQuery.taskTenantId(tenantId);
} else {
historicTaskInstanceQuery.taskWithoutTenantId(); // or omit the filter
} Type guard
boolean isValidTenant(String tenantId) {
return tenantId != null && !tenantId.isEmpty();
} Try / catch
try {
query.taskTenantId(tenantId);
} catch (FlowableIllegalArgumentException e) {
log.warn("Invalid tenantId filter: {}", e.getMessage());
query.taskWithoutTenantId();
} Prevention
- Resolve the tenant once at request entry and fail fast if missing (or default to a known tenant).
- Use taskWithoutTenantId() for no-tenant queries, never taskTenantId(null).
- Remember Flowable stores absent tenants as empty string; map '' handling explicitly.
When it happens
Trigger: Calling taskTenantId(null) — usually a tenant resolved from a multi-tenant context that is null (e.g. no tenant in the session/HTTP header), or a task.getTenantId() on a task created before tenant support.
Common situations: Multi-tenancy setups where the tenant resolver returns null for global/admin users or when the tenant header is missing; forwarding a task's tenantId when tasks were deployed without one (empty string vs null confusion).
Related errors
- app definition tenantId is null
- Must specify a case definition tenant id to migrate
- Case definition version is null
- Case instance id is null
- Case instance ids is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/bf5b7219406814bd.
Report an issue: GitHub.