flowable/flowable-engine · error · FlowableIllegalArgumentException

tenant id is null

Error message

tenant id is null

What it means

HistoricMilestoneInstanceQueryImpl.milestoneInstanceTenantId() rejects a null tenantId with FlowableIllegalArgumentException. Tenant-id filtering must be an exact string; passing null is treated as a programming mistake rather than 'no filter'.

Source

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

    public HistoricMilestoneInstanceQuery milestoneInstanceReachedAfter(Date reachedAfter) {
        this.reachedAfter = reachedAfter;
        return this;
    }

    @Override
    public HistoricMilestoneInstanceQuery orderByMilestoneName() {
        return orderBy(MilestoneInstanceQueryProperty.MILESTONE_NAME);
    }

    @Override
    public HistoricMilestoneInstanceQuery orderByTimeStamp() {
        return orderBy(MilestoneInstanceQueryProperty.MILESTONE_TIMESTAMP);
    }
    
    @Override
    public HistoricMilestoneInstanceQuery milestoneInstanceTenantId(String tenantId) {
        if (tenantId == null) {
            throw new FlowableIllegalArgumentException("tenant id is null");
        }
        this.tenantId = tenantId;
        return this;
    }

    @Override
    public HistoricMilestoneInstanceQuery milestoneInstanceTenantIdLike(String tenantIdLike) {
        if (tenantIdLike == null) {
            throw new FlowableIllegalArgumentException("tenant id is null");
        }
        this.tenantIdLike = tenantIdLike;
        return this;
    }
    
    @Override
    public HistoricMilestoneInstanceQuery milestoneInstanceWithoutTenantId() {
        this.withoutTenantId = true;
        return this;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check the tenant id for null before calling milestoneInstanceTenantId and skip the filter if filtering is intended to be global
  2. Supply the correct tenant id string
  3. Use tenantIsNotNull() or simply omit tenant filtering if you want all tenants
  4. Fix the upstream source (header/context extraction) that yields null

Example fix

// before
query.milestoneInstanceTenantId(tenantId).list();
// after
if (tenantId != null) {
    query.milestoneInstanceTenantId(tenantId);
}
List<HistoricMilestoneInstance> results = query.list();
Defensive patterns

Strategy: validation

Validate before calling

if (tenantId != null) {
    query.milestoneInstanceTenantId(tenantId);
}

Type guard

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

Try / catch

try {
    query.milestoneInstanceTenantId(tenantId);
} catch (FlowableIllegalArgumentException e) {
    if (!"tenant id is null".equals(e.getMessage())) throw e;
    // proceed without tenant filter or fail fast with a clearer message
}

Prevention

When it happens

Trigger: Calling milestoneInstanceTenantId(null), often from a variable that was supposed to hold the tenant id (e.g. request parameter or tenant context) but is null.

Common situations: Multi-tenant apps where the tenant id comes from a header/context that is absent for unauthenticated or admin paths; API wrappers forwarding nullable parameters.

Related errors


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