flowable/flowable-engine · error · ActivitiIllegalArgumentException

Candidate group is null

Error message

Candidate group is null

What it means

taskCandidateGroup(String candidateGroup) throws ActivitiIllegalArgumentException("Candidate group is null") when the candidate group id is null. The builder needs a concrete group id for the candidate-group identity-link filter. It also rejects combining this method with taskCandidateGroupIn, which is the sibling error at the same call site.

Solutions

  1. Only call taskCandidateGroup when the group id is non-null; otherwise skip the filter or use taskCandidateGroupIn with a validated list
  2. Ensure the user-to-groups resolution always returns a usable value or an empty list you branch on
  3. Validate configuration that supplies default candidate groups at startup

Example fix

// before
query.taskCandidateGroup(groups.get(0)); // IndexOutOfBounds/null risk
// after
if (groups != null && !groups.isEmpty()) {
    if (groups.size() == 1) { query.taskCandidateGroup(groups.get(0)); }
    else { query.taskCandidateGroupIn(groups); }
}
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

boolean hasCandidateGroup(String group) { return group != null && !group.trim().isEmpty(); }

Try / catch

try {
    query.taskCandidateGroup(group);
} catch (ActivitiIllegalArgumentException e) {
    log.warn("Skipping candidate-group filter: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling taskQuery.taskCandidateGroup(null); usually the group id derives from user group lookups or configuration that resolved to null.

Common situations: User has no groups so a first-group lookup returns null; tenant/authorization configuration missing a group mapping; refactoring where a group list was split and a null element slipped in.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java:514

    }

    @Override
    public TaskQueryImpl taskInvolvedUser(String involvedUser) {
        if (involvedUser == null) {
            throw new ActivitiIllegalArgumentException("Involved user is null");
        }
        if (orActive) {
            currentOrQueryObject.involvedUser = involvedUser;
        } else {
            this.involvedUser = involvedUser;
        }
        return this;
    }

    @Override
    public TaskQueryImpl taskCandidateGroup(String candidateGroup) {
        if (candidateGroup == null) {
            throw new ActivitiIllegalArgumentException("Candidate group is null");
        }

        if (candidateGroups != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both candidateGroup and candidateGroupIn");
        }

        if (orActive) {
            currentOrQueryObject.candidateGroup = candidateGroup;
        } else {
            this.candidateGroup = candidateGroup;
        }
        return this;
    }

    @Override
    public TaskQuery taskCandidateOrAssigned(String userIdForCandidateAndAssignee) {
        if (candidateGroup != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set candidateGroup");

View on GitHub (pinned to d6d39ce1c6)