{"record":{"id":"c6c2b7cf524f249b","repo":"flowable/flowable-engine","slug":"cannot-assign-a-groupid-to-a-task-assignment-that-c6c2b7","errorCode":null,"errorMessage":"Cannot assign a groupId to a task assignment that already has a userId","messagePattern":"Cannot assign a groupId to a task assignment that already has a userId","errorType":"validation","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/IdentityLinkEntity.java","lineNumber":149,"sourceCode":"    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() {\n        return taskId;\n    }\n\n    public void setTaskId(String taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public String getProcessInstanceId() {\n        return processInstanceId;\n    }\n","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/IdentityLinkEntity.java#L131-L167","documentation":"Consistency guard in flowable5 IdentityLinkEntity.setGroupId: the identity link already has a userId set, and assigning a groupId as well would make the link ambiguous (both a user and a group). The entity enforces mutual exclusivity of userId and groupId.","triggerScenarios":"Calling setGroupId on an IdentityLinkEntity whose userId is already non-null; assignment code that sets assignee first and then tries to add a group on the same entity.","commonSituations":"Custom task assignment listeners combining assignee and candidate group in one entity; converters that map 'assignee or group' fields from external systems onto a single link; reuse of entity instances across task assignments.","solutions":["Create a separate identity link for the group; use taskService.addCandidateGroup / addGroupIdentityLink.","Null out userId first only if you truly intend to convert the link.","Map external 'assignee OR group' inputs to two distinct API calls."],"exampleFix":"// before\nlink.setUserId(\"kermit\"); link.setGroupId(\"management\"); // throws\n\n// after\ntaskService.setAssignee(taskId, \"kermit\");\ntaskService.addCandidateGroup(taskId, \"management\");","handlingStrategy":"validation","validationCode":"if (link.getUserId() != null && groupId != null) {\n    throw new IllegalArgumentException(\"cannot assign group to user-based link\");\n}","typeGuard":"function isGroupLinkAssignable(link) {\n  return link.getUserId() == null;\n}","tryCatchPattern":"try {\n    taskService.addCandidateGroup(taskId, groupId);\n} catch (ActivitiException e) {\n    log.warn(\"Link conflict on task {}: {}\", taskId, e.getMessage());\n}","preventionTips":["Separate assignee and candidate-group operations into distinct calls","Avoid reusing IdentityLinkEntity instances across assignments","Validate external assignment payloads for user+group conflicts"],"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"}