flowable/flowable-engine · error · ActivitiIllegalArgumentException

process definition tenantId is null

Error message

process definition tenantId is null

What it means

Flowable/Activiti query builders validate arguments eagerly. processDefinitionTenantIdLike() throws ActivitiIllegalArgumentException when the tenantIdLike parameter is null, because a null 'like' filter cannot be translated to a meaningful SQL predicate.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/ProcessDefinitionQueryImpl.java:265

    @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;
    }

    @Override
    public ProcessDefinitionQuery messageEventSubscription(String messageName) {
        return eventSubscription("message", messageName);
    }

    @Override
    public ProcessDefinitionQuery messageEventSubscriptionName(String messageName) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null tenant id string to processDefinitionTenantIdLike()
  2. If the intent is 'any tenant', omit the tenant filter entirely or use the tenantIdLike value '*' (all tenants) instead of null
  3. Guard the caller: only add the tenant filter when a tenant id is actually available
  4. Catch ActivitiIllegalArgumentException around query construction to surface a clear 400-style message

Example fix

// before
query.processDefinitionTenantIdLike(tenantCtx.getTenantId()); // tenantId may be null
// after
if (tenantCtx.getTenantId() != null) {
    query.processDefinitionTenantIdLike(tenantCtx.getTenantId());
}
Defensive patterns

Strategy: validation

Validate before calling

if (tenantIdLike == null) {
    throw new IllegalArgumentException("tenantIdLike must not be null");
}
query.processDefinitionTenantIdLike(tenantIdLike);

Type guard

boolean hasTenantId(String t) { return t != null && !t.trim().isEmpty(); }

Try / catch

try {
    query.processDefinitionTenantIdLike(tenantId);
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("tenantId")) {
        throw new InvalidRequestException("tenantId is required");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling ProcessDefinitionQuery.processDefinitionTenantIdLike(null), typically when the tenant id comes from an uninitialized variable, a config property that is missing, or a TenantContext that returned null.

Common situations: Multi-tenant apps where the tenant id is resolved from a header/token at runtime and is absent for anonymous or misconfigured requests; unit tests constructing queries without setting tenant context.

Related errors


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