{"record":{"id":"85548ecf0718ab75","repo":"flowable/flowable-engine","slug":"invalid-query-usage-cannot-set-both-candidategrou-85548e","errorCode":null,"errorMessage":"Invalid query usage: cannot set both candidateGroup and candidateGroupIn","messagePattern":"Invalid query usage: cannot set both candidateGroup and candidateGroupIn","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java","lineNumber":626,"sourceCode":"        if (involvedGroups.isEmpty()) {\n            throw new FlowableIllegalArgumentException(\"Involved groups are empty\");\n        }\n        if (orActive) {\n            currentOrQueryObject.involvedGroups = involvedGroups;\n        } else {\n            this.involvedGroups = involvedGroups;\n        }\n        return this;\n    }\n\n    @Override\n    public TaskQueryImpl 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 (orActive) {\n            currentOrQueryObject.candidateGroup = candidateGroup;\n        } else {\n            this.candidateGroup = candidateGroup;\n        }\n        return this;\n    }\n\n    @Override\n    public TaskQuery taskCandidateOrAssigned(String userIdForCandidateAndAssignee) {\n        if (candidateGroup != null) {\n            throw new FlowableIllegalArgumentException(\"Invalid query usage: cannot set candidateGroup\");\n        }\n        if (candidateUser != null) {\n            throw new FlowableIllegalArgumentException(\"Invalid query usage: cannot set both candidateGroup and candidateUser\");\n        }","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java#L608-L644","documentation":"TaskQueryImpl.taskCandidateGroup() throws this when taskCandidateGroupIn() has already been called (candidateGroups != null). The two setters represent mutually exclusive filtering strategies (single group vs list), and combining them would produce an ambiguous query. Flowable rejects the conflicting call at build time.","triggerScenarios":"Calling taskCandidateGroup(\"g1\") after taskCandidateGroupIn(list), or building one query object incrementally/reused where both setters got invoked (including inside or() branches that share state checks).","commonSituations":"Query builder reused across requests retaining earlier state; code merged from two features each setting a different candidate filter; dynamic query composition adding both filters unconditionally.","solutions":["Use either taskCandidateGroup() or taskCandidateGroupIn(), never both on the same query.","Build a fresh query object instead of reusing a cached TaskQuery instance.","Wrap the single group in a list and call taskCandidateGroupIn(Collections.singletonList(group)) when the source may vary.","Refactor query composition logic so only one candidate filter branch executes."],"exampleFix":"// before\nquery.taskCandidateGroupIn(groups);\nquery.taskCandidateGroup(\"management\");\n// after\nif (groups != null && !groups.isEmpty()) {\n    query.taskCandidateGroupIn(groups);\n} else {\n    query.taskCandidateGroup(\"management\");\n}","handlingStrategy":"validation","validationCode":"if (useSingleGroup) {\n    query.taskCandidateGroup(group);\n} else if (groups != null && !groups.isEmpty()) {\n    query.taskCandidateGroupIn(groups);\n}","typeGuard":null,"tryCatchPattern":"try {\n    query.taskCandidateGroup(group);\n} catch (FlowableIllegalArgumentException e) {\n    logger.warn(\"Conflicting candidate filters: {}\", e.getMessage());\n    query = taskService.createTaskQuery(); // rebuild with only one filter\n}","preventionTips":["Never combine taskCandidateGroup and taskCandidateGroupIn on one query","Create a new TaskQuery instead of reusing instances","Centralize candidate filtering in one helper that enforces exclusivity","Wrap single groups in singletonList and use only taskCandidateGroupIn when the source varies"],"tags":["flowable","task-query","mutually-exclusive","candidate-group"],"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"}