flowable/flowable-engine · error · FlowableIllegalArgumentException

Provided sub scope id is null

Error message

Provided sub scope id is null

What it means

JobQueryImpl.subScopeId(String) rejects null input with FlowableIllegalArgumentException before assigning the value to the query (or the active or-query object). The library throws eagerly because a null subScopeId filter is meaningless and would produce an invalid query. Callers such as planItemInstanceId delegate into this method, so a null there also surfaces here.

Source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java:278

            this.scopeIds = scopeIds;
        }
        return this;
    }

    @Override
    public JobQuery withoutScopeId() {
        if (inOrStatement) {
            this.currentOrQueryObject.withoutScopeId = true;
        } else {
            this.withoutScopeId = true;
        }
        return this;
    }

    @Override
    public JobQueryImpl subScopeId(String subScopeId) {
        if (subScopeId == null) {
            throw new FlowableIllegalArgumentException("Provided sub scope id is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.subScopeId = subScopeId;
        } else {
            this.subScopeId = subScopeId;
        }
        return this;
    }

    @Override
    public JobQueryImpl scopeType(String scopeType) {
        if (scopeType == null) {
            throw new FlowableIllegalArgumentException("Provided scope type is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.scopeType = scopeType;
        } else {
            this.scopeType = scopeType;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the subScopeId/planItemInstanceId variable is non-null before building the query
  2. If the id came from a lookup, check that the lookup actually found the entity before querying jobs
  3. Skip the subScopeId call when the value is null and use a different filter strategy
  4. Log/inspect the upstream object to see why the id was never assigned

Example fix

// before
jobQuery.planItemInstanceId(planItemInstanceId);
// after
if (planItemInstanceId != null) {
    jobQuery.planItemInstanceId(planItemInstanceId);
} else {
    throw new IllegalStateException("Plan item instance id required for job query");
}
Defensive patterns

Strategy: validation

Validate before calling

if (subScopeId == null) { throw new IllegalArgumentException("subScopeId must not be null"); }
jobQuery.subScopeId(subScopeId);

Type guard

boolean hasSubScopeId(String id) { return id != null; }

Try / catch

try {
    jobQuery.subScopeId(subScopeId);
} catch (FlowableIllegalArgumentException e) {
    logger.warn("subScopeId was null", e);
}

Prevention

When it happens

Trigger: Calling jobQuery.subScopeId(null) directly, or jobQuery.planItemInstanceId(null) which delegates to subScopeId(null). Also triggered inside or(...) blocks.

Common situations: Passing a plan item instance id fetched from a CMMN runtime API that returned null (item not found); copying ids between process engines where the source variable was never populated; building queries from optional request parameters.

Related errors


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