{"record":{"id":"d3655d8dae546f1d","repo":"flowable/flowable-engine","slug":"invalid-query-usage-cannot-set-both-candidategrou-d3655d","errorCode":null,"errorMessage":"Invalid query usage: cannot set both candidateGroupIn and candidateGroup","messagePattern":"Invalid query usage: cannot set both candidateGroupIn and candidateGroup","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java","lineNumber":1930,"sourceCode":"            this.currentOrQueryObject.candidateGroup = candidateGroup;\n        } else {\n            this.candidateGroup = candidateGroup;\n        }\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQuery taskCandidateGroupIn(Collection<String> candidateGroups) {\n        if (candidateGroups == null) {\n            throw new FlowableIllegalArgumentException(\"Candidate group list is null\");\n        }\n\n        if (candidateGroups.isEmpty()) {\n            throw new FlowableIllegalArgumentException(\"Candidate group list is empty\");\n        }\n\n        if (candidateGroup != null) {\n            throw new FlowableIllegalArgumentException(\"Invalid query usage: cannot set both candidateGroupIn and candidateGroup\");\n        }\n\n        if (inOrStatement) {\n            this.currentOrQueryObject.candidateGroups = candidateGroups;\n        } else {\n            this.candidateGroups = candidateGroups;\n        }\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQuery taskInvolvedUser(String involvedUser) {\n        if (involvedUser == null) {\n            throw new FlowableIllegalArgumentException(\"involved user is null\");\n        }\n\n        if (inOrStatement) {\n            this.currentOrQueryObject.involvedUser = involvedUser;","sourceCodeStart":1912,"sourceCodeEnd":1948,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java#L1912-L1948","documentation":"taskCandidateGroupIn(Collection<String>) throws this error when the query already has candidateGroup (from taskCandidateGroup) set. candidateGroup and candidateGroupIn are mutually exclusive filters; only one representation can be applied to the generated SQL.","triggerScenarios":"Chaining .taskCandidateGroup(\"backoffice\").taskCandidateGroupIn(groups) on the same HistoricTaskInstanceQuery instance.","commonSituations":"Accumulating filters from multiple sources (a default single-group filter plus a user-selected group list); generic query-building code that sets whichever group criteria it has without clearing the other.","solutions":["Remove either the taskCandidateGroup(...) or the taskCandidateGroupIn(...) call on the same query object.","Use taskCandidateGroupIn(Collections.singletonList(group)) for everything so only one API is ever used.","Build a new query instance when the filter strategy changes."],"exampleFix":"// before\nquery.taskCandidateGroup(\"backoffice\");\nquery.taskCandidateGroupIn(groupList); // throws\n\n// after\nList<String> effective = new ArrayList<>(groupList);\neffective.add(\"backoffice\");\nquery.taskCandidateGroupIn(effective);","handlingStrategy":"validation","validationCode":"// merge both sources into one list and use only taskCandidateGroupIn\nList<String> allGroups = new ArrayList<>();\nif (candidateGroup != null) { allGroups.add(candidateGroup); }\nif (groupList != null) { allGroups.addAll(groupList); }\nif (!allGroups.isEmpty()) {\n    query.taskCandidateGroupIn(allGroups);\n}","typeGuard":"boolean canSetCandidateGroupIn(HistoricTaskInstanceQueryImpl q) {\n    return q.candidateGroup == null; // single group not yet set\n}","tryCatchPattern":"try {\n    query.taskCandidateGroupIn(groups);\n} catch (FlowableIllegalArgumentException e) {\n    throw new IllegalStateException(\n        \"Query already filters by candidateGroup; remove one of the two group filters\", e);\n}","preventionTips":["Use only taskCandidateGroupIn() across the codebase; wrap single groups in singletonList().","Centralize query building so group criteria cannot be set twice.","When filters arrive from multiple layers, merge them into one list first."],"tags":["flowable","query-validation","mutually-exclusive","task-query"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T16:30:33.424Z"}