{"record":{"id":"95517606e157c0f5","repo":"flowable/flowable-engine","slug":"cannot-assign-a-groupid-to-a-task-assignment-that","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":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-identitylink-service/src/main/java/org/flowable/identitylink/service/impl/persistence/entity/HistoricIdentityLinkEntityImpl.java","lineNumber":89,"sourceCode":"    }\n\n    @Override\n    public void setUserId(String userId) {\n        if (this.groupId != null && userId != null) {\n            throw new FlowableException(\"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    @Override\n    public void setGroupId(String groupId) {\n        if (this.userId != null && groupId != null) {\n            throw new FlowableException(\"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    @Override\n    public void setTaskId(String taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public String getProcessInstanceId() {\n        return processInstanceId;\n    }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-identitylink-service/src/main/java/org/flowable/identitylink/service/impl/persistence/entity/HistoricIdentityLinkEntityImpl.java#L71-L107","documentation":"The mirror invariant of setUserId: HistoricIdentityLinkEntityImpl.setGroupId throws this FlowableException when a userId is already set and a non-null groupId is being assigned. A single historic identity link cannot represent both a user and a group assignment.","triggerScenarios":"Calling setGroupId(String) on a HistoricIdentityLinkEntity whose userId field is already non-null, e.g. after creating a candidate-user link and then adding a group to the same entity.","commonSituations":"Custom code that populates both assignee-type fields on one entity; process migration code converting candidate users to candidate groups in place; hand-built entities in integration tests.","solutions":["Use separate identity link entities for the userId and the groupId.","Call setUserId(null) first if switching the link from user to group assignment.","Rework the assignment logic to choose user or group before creating the entity."],"exampleFix":"// before\nlink.setUserId(\"kermit\");\nlink.setGroupId(\"management\"); // throws\n\n// after\nlink.setUserId(null);\nlink.setGroupId(\"management\");","handlingStrategy":"validation","validationCode":"if (link.getUserId() != null && groupId != null) {\n    throw new IllegalArgumentException(\"Use a separate identity link for this group\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    link.setGroupId(groupId);\n} catch (FlowableException e) {\n    // create a new identity link entity for the group instead\n}","preventionTips":["Never reuse a user-assigned link entity for group assignment.","Decide user vs group target before constructing the identity link."],"tags":["identitylink","assignment","invariant","history"],"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"}