flowable/flowable-engine · error · FlowableIllegalArgumentException

deploymentTenantId is null

Error message

deploymentTenantId is null

What it means

AppDeploymentQueryImpl.deploymentTenantId(String) throws FlowableIllegalArgumentException when the tenantId argument is null. The Flowable query builders validate each criterion eagerly at setter time so that an invalid query fails at construction rather than producing a broken SQL query at execution. Passing null for an exact tenant filter is not a supported way to express 'no filter' — simply omit the call instead.

Solutions

  1. Ensure a non-null tenant id is resolved before building the query (e.g. require the tenantId request parameter or resolve it from the authenticated principal)
  2. Only call deploymentTenantId(...) when the value is non-null; omit it to query across all tenants
  3. If a default tenant is acceptable, fall back to a constant (e.g. "default") when the resolved id is null

Example fix

// before
query.deploymentTenantId(tenantContext.getTenantId());
// after
String tenantId = tenantContext.getTenantId();
if (tenantId != null) {
    query.deploymentTenantId(tenantId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (tenantId == null || tenantId.isEmpty()) {
    throw new IllegalArgumentException("tenantId must be provided for deploymentTenantId filter, or omit the filter");
}
query.deploymentTenantId(tenantId);

Type guard

boolean hasTenant = tenantId instanceof String s && !s.isEmpty();

Try / catch

try {
    query.deploymentTenantId(tenantId);
} catch (FlowableIllegalArgumentException e) {
    // tenantId was null — build query without tenant filter or rethrow with context
    logger.warn("No tenant id resolved; querying all tenants", e);
}

Prevention

When it happens

Trigger: Calling appDeploymentService.createDeploymentQuery().deploymentTenantId(null), typically when the tenant id is supplied by a variable, request parameter, or config value that is null at query time.

Common situations: REST/API layers forwarding a missing tenantId query parameter; multi-tenant apps where TenantContext.getTenantId() returns null before tenant resolution; refactoring that replaced an optional-tenant path with an unconditional setter call.

Related errors


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

Appendix: source

Thrown at modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/repository/AppDeploymentQueryImpl.java:123

            throw new FlowableIllegalArgumentException("deploymentCategoryExclude is null");
        }
        this.categoryNotEquals = deploymentCategoryNotEquals;
        return this;
    }
    
    @Override
    public AppDeploymentQueryImpl deploymentKey(String deploymentKey) {
        if (deploymentKey == null) {
            throw new FlowableIllegalArgumentException("deploymentKey is null");
        }
        this.key = deploymentKey;
        return this;
    }

    @Override
    public AppDeploymentQueryImpl deploymentTenantId(String tenantId) {
        if (tenantId == null) {
            throw new FlowableIllegalArgumentException("deploymentTenantId is null");
        }
        this.tenantId = tenantId;
        return this;
    }

    @Override
    public AppDeploymentQueryImpl deploymentTenantIdLike(String tenantIdLike) {
        if (tenantIdLike == null) {
            throw new FlowableIllegalArgumentException("deploymentTenantIdLike is null");
        }
        this.tenantIdLike = tenantIdLike;
        return this;
    }

    @Override
    public AppDeploymentQueryImpl deploymentWithoutTenantId() {
        this.withoutTenantId = true;
        return this;

View on GitHub (pinned to d6d39ce1c6)