{"record":{"id":"51060bcf037bebec","repo":"flowable/flowable-engine","slug":"invalid-query-usage-cannot-set-both-candidategrou","errorCode":null,"errorMessage":"Invalid query usage: cannot set both candidateGroup and candidateGroupIn","messagePattern":"Invalid query usage: cannot set both candidateGroup and candidateGroupIn","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java","lineNumber":1908,"sourceCode":"            throw new FlowableIllegalArgumentException(\"Candidate user is null\");\n        }\n\n        if (inOrStatement) {\n            this.currentOrQueryObject.candidateUser = candidateUser;\n        } else {\n            this.candidateUser = candidateUser;\n        }\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQuery taskCandidateGroup(String candidateGroup) {\n        if (candidateGroup == null) {\n            throw new FlowableIllegalArgumentException(\"Candidate group is null\");\n        }\n\n        if (candidateGroups != null) {\n            throw new FlowableIllegalArgumentException(\"Invalid query usage: cannot set both candidateGroup and candidateGroupIn\");\n        }\n\n        if (inOrStatement) {\n            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\");","sourceCodeStart":1890,"sourceCodeEnd":1926,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java#L1890-L1926","documentation":"taskCandidateGroup(String) throws this error when the query already has candidateGroups (from taskCandidateGroupIn) set. The two filters are mutually exclusive: candidateGroup matches exactly one group while candidateGroupIn matches any of a list, and the SQL generator supports only one form per query object.","triggerScenarios":"Chaining .taskCandidateGroupIn(Arrays.asList(\"a\",\"b\")).taskCandidateGroup(\"a\") — or the reverse order with taskCandidateGroup called before taskCandidateGroupIn — on the same HistoricTaskInstanceQuery instance.","commonSituations":"Building query filters dynamically where different code paths each set a candidate-group criterion; UIs that let users pick either a single group or a group list but accumulate conditions instead of replacing them.","solutions":["Choose one filter: remove either the taskCandidateGroup(...) call or the taskCandidateGroupIn(...) call on the same query.","Use a fresh HistoricTaskInstanceQuery instance for each distinct filter combination.","Represent a single group as a one-element list and use taskCandidateGroupIn(Collections.singletonList(group)) exclusively."],"exampleFix":"// before\nquery.taskCandidateGroupIn(groups);\nquery.taskCandidateGroup(\"backoffice\"); // throws\n\n// after\nList<String> effectiveGroups = new ArrayList<>(groups);\neffectiveGroups.add(\"backoffice\");\nquery.taskCandidateGroupIn(effectiveGroups);","handlingStrategy":"validation","validationCode":"// choose ONE form before building the query\nboolean useGroupList = groupList != null && !groupList.isEmpty();\nif (useGroupList) {\n    query.taskCandidateGroupIn(groupList);\n} else if (candidateGroup != null) {\n    query.taskCandidateGroup(candidateGroup);\n}","typeGuard":"boolean canSetCandidateGroup(HistoricTaskInstanceQueryImpl q) {\n    return q.candidateGroups == null; // group list not yet set\n}","tryCatchPattern":"try {\n    query.taskCandidateGroup(candidateGroup);\n} catch (FlowableIllegalArgumentException e) {\n    throw new IllegalStateException(\n        \"Query already filters by candidateGroupIn; remove one of the two group filters\", e);\n}","preventionTips":["Standardize on taskCandidateGroupIn(Collections.singletonList(g)) so only one API is used.","Build group filters from a single accumulation point instead of scattered setter calls.","Create a fresh query instance per request/filter combination."],"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-18T11:17:12.947Z"}