flowable/flowable-engine · error · FlowableIllegalArgumentException

Provided sub scope id is null

Error message

Provided sub scope id is null

What it means

ExternalWorkerJobQueryImpl.subScopeId() rejects a null sub-scope id. The sub-scope id identifies the finer-grained entity (such as a plan item instance) within a scope; a null value would make the filter meaningless, so Flowable throws FlowableIllegalArgumentException immediately. This method is also the target of planItemInstanceId(), which forwards its argument here.

Solutions

  1. Pass a non-null sub scope id; skip the filter call when the value is null
  2. Wrap the value in Objects.requireNonNull checks at your query-builder layer
  3. Fix upstream lookups that return null (e.g. missing plan item instance)
  4. Catch FlowableIllegalArgumentException around query construction

Example fix

// before
query.planItemInstanceId(planItem.getId()); // planItem can be null
// after
if (planItem != null) {
    query.planItemInstanceId(planItem.getId());
}
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

boolean hasSubScopeId(String subScopeId) { return subScopeId != null && !subScopeId.trim().isEmpty(); }

Try / catch

try {
    query.subScopeId(subScopeId);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Null sub scope id in job query: {}", e.getMessage());
    throw new InvalidQueryException(e);
}

Prevention

When it happens

Trigger: Calling externalWorkerJobQuery.subScopeId(null) directly, or calling planItemInstanceId(null) which delegates to subScopeId, including inside an or() block.

Common situations: Chaining case/plan-item filters built from optional variables; passing an uninitialized field or a null result of a lookup into planItemInstanceId.

Related errors


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

Appendix: source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/ExternalWorkerJobQueryImpl.java:276

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

    @Override
    public ExternalWorkerJobQuery 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 ExternalWorkerJobQueryImpl 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)