flowable/flowable-engine · error · FlowableIllegalArgumentException

at least one of userId or groups must be provided

Error message

at least one of userId or groups must be provided

What it means

ExternalWorkerJobQueryImpl.forUserOrGroups(String userId, Collection<String> groups) requires at least one non-null identity: either a userId or a non-empty groups collection. Calling it with userId == null and groups == null/empty yields FlowableIllegalArgumentException. It sets the authorizedUser/authorizedGroups filters used for permission-scoped external worker job queries.

Solutions

  1. Pass at least the current user's id, e.g. forUserOrGroups(userId, userGroups)
  2. If neither is available, do not call forUserOrGroups() and decide explicitly whether the query should be unscoped (and whether that is allowed)
  3. Validate inputs before the call and return a domain-level 'identity filter required' error
  4. Check that group resolution (e.g. from identity service) actually returns members

Example fix

// before
query.forUserOrGroups(userId, groups); // both may be empty
// after
boolean hasGroups = groups != null && !groups.isEmpty();
if (userId != null || hasGroups) {
    query.forUserOrGroups(userId, groups);
} else {
    throw new IllegalArgumentException("Identity filter required");
}
Defensive patterns

Strategy: validation

Validate before calling

boolean hasUser = userId != null;
boolean hasGroups = groups != null && !groups.isEmpty();
if (!hasUser && !hasGroups) {
    throw new IllegalArgumentException("Provide userId or groups for forUserOrGroups");
}
externalWorkerJobQuery.forUserOrGroups(userId, groups);

Type guard

boolean hasIdentity(String userId, Collection<String> groups) {
    return userId != null || (groups != null && !groups.isEmpty());
}

Prevention

When it happens

Trigger: Calling forUserOrGroups(null, null), forUserOrGroups(null, Collections.emptyList()), or with a groups collection that was filtered down to empty at runtime.

Common situations: Permission-aware dashboards where both user and group filters are optional in the UI but mandatory in the query API; dynamic group lists emptied by prior filtering.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

            this.tenantIdLike = tenantIdLike;
        }
        return this;
    }

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

    @Override
    public ExternalWorkerJobQuery forUserOrGroups(String userId, Collection<String> groups) {
        if (userId == null && (groups == null || groups.isEmpty())) {
            throw new FlowableIllegalArgumentException("at least one of userId or groups must be provided");
        }

        if (inOrStatement) {
            this.currentOrQueryObject.authorizedUser = userId;
            this.currentOrQueryObject.authorizedGroups = groups;
        } else {
            this.authorizedUser = userId;
            this.authorizedGroups = groups;
        }

        return this;
    }

    @Override
    public ExternalWorkerJobQuery lockOwner(String lockOwner) {
        if (inOrStatement) {
            this.currentOrQueryObject.lockOwner = lockOwner;
        } else {

View on GitHub (pinned to d6d39ce1c6)