{"record":{"id":"4e728e65b57f9fad","repo":"flowable/flowable-engine","slug":"candidate-user-is-null","errorCode":null,"errorMessage":"Candidate user is null","messagePattern":"Candidate user is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java","lineNumber":1890,"sourceCode":"\n    @Override\n    public HistoricTaskInstanceQuery taskFormKey(String formKey) {\n        if (formKey == null) {\n            throw new FlowableIllegalArgumentException(\"Task formKey is null\");\n        }\n\n        if (inOrStatement) {\n            currentOrQueryObject.formKey = formKey;\n        } else {\n            this.formKey = formKey;\n        }\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQuery taskCandidateUser(String candidateUser) {\n        if (candidateUser == null) {\n            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\");","sourceCodeStart":1872,"sourceCodeEnd":1908,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java#L1872-L1908","documentation":"HistoricTaskInstanceQueryImpl.taskCandidateUser(String) throws FlowableIllegalArgumentException when the candidateUser argument is null. Flowable query builders validate required filter values eagerly so that an invalid query fails at construction time rather than producing an SQL error or empty results at execution. The field is only assigned after the null check passes.","triggerScenarios":"Calling historicTaskInstanceQuery.taskCandidateUser(null), typically because a variable holding the user id was null (e.g. userTask.getCandidateUser() returned null, or an unresolved request parameter was passed straight through).","commonSituations":"Passing through a task assignment value that was never set in the BPMN model; wiring a REST query parameter that the client omitted; refactoring where a default user constant was removed and the variable defaults to null.","solutions":["Pass a non-null user id string to taskCandidateUser(); verify the value with a null check first.","If the candidate user is optional, skip calling taskCandidateUser() entirely instead of passing null.","If the candidate user is unknown but identity links matter, use taskCandidateGroup()/taskCandidateGroupIn() or taskInvolvedUser() filters instead."],"exampleFix":"// before\nString user = task.getCandidateUser();\nquery.taskCandidateUser(user); // NPE-free but throws if user is null\n\n// after\nif (task.getCandidateUser() != null) {\n    query.taskCandidateUser(task.getCandidateUser());\n}","handlingStrategy":"validation","validationCode":"if (candidateUser == null || candidateUser.isEmpty()) {\n    throw new IllegalArgumentException(\"candidateUser must be a non-empty user id\");\n}\nhistoricTaskInstanceQuery.taskCandidateUser(candidateUser);","typeGuard":"boolean isValidUser(String userId) {\n    return userId != null && !userId.trim().isEmpty();\n}","tryCatchPattern":"try {\n    query.taskCandidateUser(candidateUser);\n} catch (FlowableIllegalArgumentException e) {\n    // log and rebuild the query without this filter\n    log.warn(\"Invalid candidateUser filter: {}\", e.getMessage());\n}","preventionTips":["Null-check values taken from task identity links (getCandidateUser) before using them as filters.","Skip optional filter setters rather than passing null to them.","Sanitize and default REST query parameters before building Flowable queries."],"tags":["flowable","query-validation","null-argument","task-query"],"backgroundTag":"null-argument","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"}