flowable/flowable-engine · error · FlowableIllegalArgumentException

tenant id is null

Error message

tenant id is null

What it means

HistoricPlanItemInstanceQueryImpl.planItemInstanceTenantIdLike() validates its argument and throws FlowableIllegalArgumentException when a null tenantIdLike is passed. The query API refuses null because a null 'like' filter is ambiguous — use the non-like tenantId filter or omit it entirely. This is a fail-fast guard so misconfigured queries break at build time rather than returning wrong results.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricPlanItemInstanceQueryImpl.java:415

            this.tenantId = tenantId;
        }
        return this;
    }

    @Override
    public HistoricPlanItemInstanceQuery planItemInstanceWithoutTenantId() {
        if (inOrStatement) {
            this.currentOrQueryObject.withoutTenantId = true;
        } else {
            this.withoutTenantId = true;
        }
        return this;
    }
    
    @Override
    public HistoricPlanItemInstanceQuery planItemInstanceTenantIdLike(String tenantIdLike) {
        if (tenantIdLike == null) {
            throw new FlowableIllegalArgumentException("tenant id is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.tenantIdLike = tenantIdLike;
        } else {
            this.tenantIdLike = tenantIdLike;
        }
        return this;
    }

    @Override
    public HistoricPlanItemInstanceQuery createdBefore(Date createdBefore) {
        if (inOrStatement) {
            this.currentOrQueryObject.createdBefore = createdBefore;
        } else {
            this.createdBefore = createdBefore;
        }
        return this;
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null string to planItemInstanceTenantIdLike
  2. If you do not need to filter by tenant, do not call the method at all
  3. If the filter value is optional, guard it: only call the method when the value is non-null
  4. If an exact (non-like) tenant match is intended, use planItemInstanceTenantId instead

Example fix

// before
query.planItemInstanceTenantIdLike(tenantId); // NPE-ish failure when tenantId is null
// after
if (tenantId != null) {
    query.planItemInstanceTenantIdLike(tenantId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (tenantIdLike == null) {
    throw new IllegalArgumentException("tenantIdLike must not be null; omit the filter or use planItemInstanceTenantId");
}
historicPlanItemInstanceQuery.planItemInstanceTenantIdLike(tenantIdLike);

Type guard

boolean isUsableTenantFilter(String tenantIdLike) {
    return tenantIdLike != null && !tenantIdLike.isEmpty();
}

Try / catch

try {
    query.planItemInstanceTenantIdLike(tenantIdLike);
} catch (FlowableIllegalArgumentException e) {
    // tenantIdLike was null — fall back to unfiltered query or fix input
}

Prevention

When it happens

Trigger: Calling planItemInstanceTenantIdLike(null) on a HistoricPlanItemInstanceQuery, typically when the tenant id comes from a variable, config, or request parameter that is null.

Common situations: Multi-tenant setups where the tenant id is resolved from an authenticated principal or header that is absent; passing an unset configuration property straight into the query builder.

Related errors


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