{"record":{"id":"41ce5bcbaccd6d46","repo":"Activiti/Activiti","slug":"you-cannot-assign-a-task-to-assignee-due-it-is","errorCode":null,"errorMessage":"You cannot assign a task to ${assignee} due it is not a candidate for it","messagePattern":"You cannot assign a task to (.+?) due it is not a candidate for it","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-api-impl/activiti-api-task-runtime-impl/src/main/java/org/activiti/runtime/api/impl/TaskRuntimeImpl.java","lineNumber":547,"sourceCode":"                    taskId +\n                    \" for user: \" +\n                    authenticatedUserId +\n                    \" (with groups: \" +\n                    userGroups +\n                    \" & with roles: \" +\n                    userRoles +\n                    \")\"\n                );\n            }\n            return taskService.getIdentityLinksForTask(taskId);\n        }\n        throw new IllegalStateException(\"There is no authenticated user, we need a user authenticated to find tasks\");\n    }\n\n    private void assertAssigneeIsACandidateUser(String taskId, String assignee) {\n        List<String> userCandidates = userCandidates(taskId);\n        if (!userCandidates.contains(assignee)) {\n            throw new IllegalStateException(\n                \"You cannot assign a task to \" + assignee + \" due it is not a candidate for it\"\n            );\n        }\n    }\n\n    private void reassignTask(String taskId, String assignee) {\n        releaseTask(taskId);\n        taskService.claim(taskId, assignee);\n    }\n\n    private void releaseTask(String taskId) {\n        assertCanReleaseTask(taskId);\n        taskService.unclaim(taskId);\n    }\n\n    private void assertCanReleaseTask(String taskId) {\n        Task task = task(taskId);\n","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-api-impl/activiti-api-task-runtime-impl/src/main/java/org/activiti/runtime/api/impl/TaskRuntimeImpl.java#L529-L565","documentation":"When assigning a task, TaskRuntimeImpl.assertAssigneeIsACandidateUser enforces that the new assignee is one of the task's candidate users. The low-level engine allows assigning anyone, but the higher-level TaskRuntime restricts claims/assignments to candidates. If the target user is not a candidate, this IllegalStateException is thrown.","triggerScenarios":"taskRuntime.assign(new AssignTaskPayload(taskId, assignee)) where assignee is not present in the task's candidate user list (userCandidates(taskId)); also hit on claim flows where the claiming user was never added as candidate.","commonSituations":"Trying to hand a task to a colleague who was never added as candidate user; process definitions with candidate-groups only (so individual users aren't 'candidate users' as resolved by userCandidates); UI allowing free-text assignee input.","solutions":["Add the user as a candidate first (taskRuntime.addCandidateUser / addUserCandidateUser) then assign","Assign via candidate group membership so the user qualifies as candidate","Use engine-level taskService.setAssignee(taskId, assignee) when unrestricted assignment is intended","Update the BPMN process definition to include the intended users/groups as candidates"],"exampleFix":"// before\ntaskRuntime.assign(new AssignTaskPayload(taskId, \"mary\")); // mary not a candidate -> throws\n// after\ntaskRuntime.addCandidateUser(new CandidateUserPayload(taskId, \"mary\"));\ntaskRuntime.assign(new AssignTaskPayload(taskId, \"mary\"));","handlingStrategy":"validation","validationCode":"List<String> candidates = taskRuntime.userCandidates(taskId); // or identity links\nif (!candidates.contains(assignee)) { taskRuntime.addCandidateUser(new CandidateUserPayload(taskId, assignee)); }","typeGuard":null,"tryCatchPattern":"try { taskRuntime.assign(payload); } catch (IllegalStateException e) { /* add candidate then retry once */ }","preventionTips":["Model assignment flows as candidate-first","Keep BPMN candidate users/groups in sync with real org data","Constrain UI assignee pickers to candidate lists"],"tags":["activiti","task-runtime","assignment","candidates"],"backgroundTag":"invalid-state-transition","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}