{"record":{"id":"30c4025d2c2c75be","repo":"flowable/flowable-engine","slug":"invalid-query-usage-cannot-set-both-candidategrou-30c402","errorCode":null,"errorMessage":"Invalid query usage: cannot set both candidateGroup and candidateUser","messagePattern":"Invalid query usage: cannot set both candidateGroup and candidateUser","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java","lineNumber":643,"sourceCode":"        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        }\n\n        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(Collection<String> candidateGroups) {\n        if (candidateGroups == null) {\n            throw new FlowableIllegalArgumentException(\"Candidate group list is null\");\n        }","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java#L625-L661","documentation":"TaskQueryImpl.taskCandidateOrAssigned() throws this when candidateUser was already set. A task query cannot combine a plain candidateUser filter with the candidateOrAssigned (both candidate and assignee) filter, since their identity-link semantics conflict. Flowable validates this at query build time.","triggerScenarios":"Calling taskQuery.taskCandidateOrAssigned(userId) after taskCandidateUser(user), or setting candidateUser inside an or() branch before invoking candidateOrAssigned.","commonSituations":"Incremental query construction where two filters were added; merging code that used candidateUser with code migrated to candidateOrAssigned; reused query objects carrying state.","solutions":["Use taskCandidateOrAssigned() alone when you want candidate-or-assignee semantics; drop the separate taskCandidateUser() call.","Build a fresh TaskQuery rather than reusing one where candidateUser was previously set.","Refactor shared query-builder helpers so only one candidate-user-style filter is applied.","Check or() branch composition to ensure candidateUser and candidateOrAssigned are not both set."],"exampleFix":"// before\nquery.taskCandidateUser(userId);\nquery.taskCandidateOrAssigned(userId);\n// after\nquery.taskCandidateOrAssigned(userId); // covers candidate and assignee","handlingStrategy":"validation","validationCode":"query.taskCandidateOrAssigned(userId); // do not also call taskCandidateUser on the same query","typeGuard":null,"tryCatchPattern":"try {\n    query.taskCandidateOrAssigned(userId);\n} catch (FlowableIllegalArgumentException e) {\n    logger.warn(\"candidateUser already set: {}\", e.getMessage());\n    query = taskService.createTaskQuery();\n}","preventionTips":["Drop taskCandidateUser() when switching to taskCandidateOrAssigned() semantics","Never mix candidate filters in the same query or or() branch","Instantiate fresh TaskQuery objects per request","Audit query-builder helpers for multiple candidate-setter calls"],"tags":["flowable","task-query","mutually-exclusive","candidate-user"],"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"}