{"record":{"id":"ff6554ef7d5de657","repo":"flowable/flowable-engine","slug":"candidate-group-list-is-empty-ff6554","errorCode":null,"errorMessage":"Candidate group list is empty","messagePattern":"Candidate group list is empty","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java","lineNumber":556,"sourceCode":"        if (orActive) {\n            currentOrQueryObject.bothCandidateAndAssigned = true;\n            currentOrQueryObject.userIdForCandidateAndAssignee = userIdForCandidateAndAssignee;\n        } else {\n            this.bothCandidateAndAssigned = true;\n            this.userIdForCandidateAndAssignee = userIdForCandidateAndAssignee;\n        }\n\n        return this;\n    }\n\n    @Override\n    public TaskQuery taskCandidateGroupIn(List<String> candidateGroups) {\n        if (candidateGroups == null) {\n            throw new ActivitiIllegalArgumentException(\"Candidate group list is null\");\n        }\n\n        if (candidateGroups.isEmpty()) {\n            throw new ActivitiIllegalArgumentException(\"Candidate group list is empty\");\n        }\n\n        if (candidateGroup != null) {\n            throw new ActivitiIllegalArgumentException(\"Invalid query usage: cannot set both candidateGroupIn and candidateGroup\");\n        }\n\n        if (orActive) {\n            currentOrQueryObject.candidateGroups = candidateGroups;\n        } else {\n            this.candidateGroups = candidateGroups;\n        }\n        return this;\n    }\n\n    @Override\n    public TaskQuery taskTenantId(String tenantId) {\n        if (tenantId == null) {\n            throw new ActivitiIllegalArgumentException(\"task tenant id is null\");","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java#L538-L574","documentation":"TaskQueryImpl.taskCandidateGroupIn(List<String>) throws ActivitiIllegalArgumentException when the candidateGroups list is empty. An empty IN list would generate invalid or meaningless SQL (IN ()), so the engine rejects it at query-build time. Callers must pass at least one candidate group.","triggerScenarios":"Calling taskQuery.taskCandidateGroupIn(new ArrayList<>()) or passing a collection that was filtered down to zero elements before the query was built.","commonSituations":"A user belongs to no groups, group filtering removed all entries, or a CSV/config value split into zero tokens; the query is then built unconditionally.","solutions":["Check list.isEmpty() before calling taskCandidateGroupIn and handle the no-groups case explicitly (e.g. skip the candidate-group filter or return an empty result by policy).","Combine the null and empty checks into one guard helper reused by all query builders.","Catch ActivitiIllegalArgumentException around query construction and report that no candidate groups were supplied."],"exampleFix":"// before\ntaskQuery.taskCandidateGroupIn(userGroups); // may be empty\n\n// after\nif (userGroups != null && !userGroups.isEmpty()) {\n    taskQuery.taskCandidateGroupIn(userGroups);\n} else {\n    return Collections.emptyList(); // policy: no groups => no candidate tasks\n}","handlingStrategy":"validation","validationCode":"if (candidateGroups == null || candidateGroups.isEmpty()) {\n    return Collections.emptyList(); // or skip the filter\n}\ntaskQuery.taskCandidateGroupIn(candidateGroups);","typeGuard":"boolean isNonEmpty(List<String> list) { return list != null && !list.isEmpty(); }","tryCatchPattern":"try {\n    return taskQuery.taskCandidateGroupIn(groups).list();\n} catch (ActivitiIllegalArgumentException e) {\n    log.warn(\"Empty candidate group filter rejected: {}\", e.getMessage());\n    return Collections.emptyList();\n}","preventionTips":["Decide explicit policy for 'no groups' (empty result vs unfiltered query)","Guard both null and empty in the same check","Log which filter was rejected to speed up debugging"],"tags":["activiti","flowable","task-query","argument-validation"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}