{"record":{"id":"7ae7ddda14f3fe61","repo":"flowable/flowable-engine","slug":"cannot-assign-a-userid-to-a-task-assignment-that-a-7ae7dd","errorCode":null,"errorMessage":"Cannot assign a userId to a task assignment that already has a groupId","messagePattern":"Cannot assign a userId to a task assignment that already has a groupId","errorType":"validation","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/IdentityLinkEntity.java","lineNumber":137,"sourceCode":"    }\n\n    @Override\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    @Override\n    public String getUserId() {\n        return userId;\n    }\n\n    public void setUserId(String userId) {\n        if (this.groupId != null && userId != null) {\n            throw new ActivitiException(\"Cannot assign a userId to a task assignment that already has a groupId\");\n        }\n        this.userId = userId;\n    }\n\n    @Override\n    public String getGroupId() {\n        return groupId;\n    }\n\n    public void setGroupId(String groupId) {\n        if (this.userId != null && groupId != null) {\n            throw new ActivitiException(\"Cannot assign a groupId to a task assignment that already has a userId\");\n        }\n        this.groupId = groupId;\n    }\n\n    @Override\n    public String getTaskId() {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/IdentityLinkEntity.java#L119-L155","documentation":"Same invariant as the historic variant but for runtime IdentityLinkEntity: a runtime identity link is either user- or group-based. setUserId throws ActivitiException when groupId is already set and a non-null userId is assigned.","triggerScenarios":"Calling setUserId on a runtime IdentityLinkEntity (e.g., task candidate/assignee links) that already has a groupId set; custom task listeners or assignment code mutating one entity for both a candidate group and an assignee.","commonSituations":"TaskListener/assignment handler code that adds both candidateGroup and assignee to the same IdentityLinkEntity object; custom REST/API layers building identity links from mixed request payloads; migration tools converting candidate groups to user assignments in place.","solutions":["Add a new IdentityLinkEntity for the assignee instead of reusing the candidate-group link; use taskService.addUserIdentityLink / setAssignee.","Clear groupId first if intentionally converting the link to user-based.","Keep candidate groups and assignees as distinct links — that is how the API and UI expect them."],"exampleFix":"// before\nIdentityLinkEntity link = ...; link.setGroupId(\"management\"); link.setUserId(\"kermit\"); // throws\n\n// after\ntaskService.addCandidateGroup(taskId, \"management\");\ntaskService.setAssignee(taskId, \"kermit\");","handlingStrategy":"validation","validationCode":"if (link.getGroupId() != null && userId != null) {\n    throw new IllegalArgumentException(\"cannot assign user to group-based link\");\n}","typeGuard":"function isUserLinkAssignable(link) {\n  return link.getGroupId() == null;\n}","tryCatchPattern":"try {\n    taskService.addUserIdentityLink(taskId, userId, IdentityLinkType.CANDIDATE);\n} catch (ActivitiException e) {\n    log.warn(\"Link conflict on task {}: {}\", taskId, e.getMessage());\n}","preventionTips":["Use taskService.setAssignee/addCandidateGroup instead of touching entities","Model candidate group and assignee as separate links","Review TaskListener code for mixed principal assignments"],"tags":["identity-link","assignment","task"],"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-18T16:30:33.424Z"}