{"record":{"id":"d85531f98204aca5","repo":"flowable/flowable-engine","slug":"cannot-assign-a-userid-to-a-task-assignment-that-a-d85531","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":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-identitylink-service/src/main/java/org/flowable/identitylink/service/impl/persistence/entity/IdentityLinkEntityImpl.java","lineNumber":129,"sourceCode":"    @Override\n    public String getType() {\n        return type;\n    }\n\n    @Override\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    @Override\n    public String getUserId() {\n        return userId;\n    }\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","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-identitylink-service/src/main/java/org/flowable/identitylink/service/impl/persistence/entity/IdentityLinkEntityImpl.java#L111-L147","documentation":"IdentityLinkEntityImpl.setUserId enforces the same user-vs-group exclusivity for runtime identity links: if the entity's groupId is already set, assigning a non-null userId throws this FlowableException. It is called by engine code such as getDefaultIdentityLinks when resolving default task identity links.","triggerScenarios":"Engine resolution of default identity links (getDefaultIdentityLinks) or direct API calls setting a userId on a runtime IdentityLinkEntity that already carries a groupId; typically caused by a task/definition configured with both candidate group and candidate user data colliding into one entity.","commonSituations":"BPMN task definitions with misconfigured candidateUser and candidateGroup on the same link; custom identity-link providers that populate both fields; programmatic assignment code written against older Flowable versions that tolerated both fields.","solutions":["Ensure each identity link entity represents exactly one assignment: split user and group links into separate entities.","Check the process definition so candidateGroup and candidateUser are declared as distinct candidate entries, not merged.","Clear groupId (setGroupId(null)) before setting a userId when intentionally converting the link."],"exampleFix":"// before\nidentityLink.setGroupId(\"sales\");\nidentityLink.setUserId(\"kermit\"); // throws\n\n// after\nIdentityLinkEntity groupLink = createLink(\"sales\", null);\nIdentityLinkEntity userLink = createLink(null, \"kermit\");","handlingStrategy":"validation","validationCode":"if (identityLink.getGroupId() != null && userId != null) {\n    throw new IllegalArgumentException(\"Split user and group into separate identity links\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    identityLink.setUserId(userId);\n} catch (FlowableException e) {\n    // fall back to creating a fresh IdentityLinkEntity for the user\n}","preventionTips":["Audit BPMN task definitions so candidateUser and candidateGroup entries stay distinct.","Keep assignment handlers/ listeners assigning one target type per link entity."],"tags":["identitylink","assignment","invariant","runtime"],"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"}