flowable/flowable-engine · error · FlowableIllegalArgumentException

app definition tenantId is null

Error message

app definition tenantId is null

What it means

appDefinitionTenantId() filters app definitions by exact tenant id and rejects null, because the subsequent SQL equality comparison requires a concrete tenant id value. Flowable throws FlowableIllegalArgumentException early at query-construction time rather than returning empty or broken results.

Source

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

    protected void checkVersion(Integer version) {
        if (version == null) {
            throw new FlowableIllegalArgumentException("version is null");
        } else if (version <= 0) {
            throw new FlowableIllegalArgumentException("version must be positive");
        }
    }

    @Override
    public AppDefinitionQueryImpl latestVersion() {
        this.latest = true;
        return this;
    }

    @Override
    public AppDefinitionQuery appDefinitionTenantId(String tenantId) {
        if (tenantId == null) {
            throw new FlowableIllegalArgumentException("app definition tenantId is null");
        }
        this.tenantId = tenantId;
        return this;
    }

    @Override
    public AppDefinitionQuery appDefinitionTenantIdLike(String tenantIdLike) {
        if (tenantIdLike == null) {
            throw new FlowableIllegalArgumentException("app definition tenantId is null");
        }
        this.tenantIdLike = tenantIdLike;
        return this;
    }

    @Override
    public AppDefinitionQuery appDefinitionWithoutTenantId() {
        this.withoutTenantId = true;
        return this;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass the actual tenant id string; verify tenant resolution returns a value before querying.
  2. Skip the tenant filter if querying across tenants is intended (requires appropriate authorization).
  3. Throw or return a clear 'tenant required' error in your own layer instead of passing null into the query.

Example fix

// before
String tenantId = securityContext.getTenantId(); // may be null
AppDefinition definition = repositoryService.createAppDefinitionQuery()
    .appDefinitionTenantId(tenantId).latestVersion().singleResult();

// after
String tenantId = securityContext.getTenantId();
if (tenantId == null) {
    throw new IllegalStateException("No tenant resolved for current request");
}
AppDefinition definition = repositoryService.createAppDefinitionQuery()
    .appDefinitionTenantId(tenantId).latestVersion().singleResult();
Defensive patterns

Strategy: validation

Validate before calling

if (tenantId == null || tenantId.isEmpty()) { throw new IllegalStateException("tenant id is required"); }

Type guard

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

Try / catch

try { query.appDefinitionTenantId(tenantId); } catch (FlowableIllegalArgumentException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "tenant id required"); }

Prevention

When it happens

Trigger: Calling AppDefinitionQuery.appDefinitionTenantId(null) — typically when the tenant is resolved from a security context, header, or authenticated user and the resolution returned null.

Common situations: Multi-tenant apps where the tenant header is missing; code running outside a tenant-aware context (e.g. background jobs); security context not yet populated when the query is built.

Related errors


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