flowable/flowable-engine · error · FlowableException

Cannot assign a groupId to a task assignment that already…

Error message

Cannot assign a groupId to a task assignment that already has a userId

What it means

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.

Solutions

  1. Use separate identity link entities for the userId and the groupId.
  2. Call setUserId(null) first if switching the link from user to group assignment.
  3. Rework the assignment logic to choose user or group before creating the entity.

Example fix

// before
link.setUserId("kermit");
link.setGroupId("management"); // throws

// after
link.setUserId(null);
link.setGroupId("management");
Defensive patterns

Strategy: validation

Validate before calling

if (link.getUserId() != null && groupId != null) {
    throw new IllegalArgumentException("Use a separate identity link for this group");
}

Try / catch

try {
    link.setGroupId(groupId);
} catch (FlowableException e) {
    // create a new identity link entity for the group instead
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/95517606e157c0f5. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-identitylink-service/src/main/java/org/flowable/identitylink/service/impl/persistence/entity/HistoricIdentityLinkEntityImpl.java:89

    }

    @Override
    public void setUserId(String userId) {
        if (this.groupId != null && userId != null) {
            throw new FlowableException("Cannot assign a userId to a task assignment that already has a groupId");
        }
        this.userId = userId;
    }

    @Override
    public String getGroupId() {
        return groupId;
    }

    @Override
    public void setGroupId(String groupId) {
        if (this.userId != null && groupId != null) {
            throw new FlowableException("Cannot assign a groupId to a task assignment that already has a userId");
        }
        this.groupId = groupId;
    }

    @Override
    public String getTaskId() {
        return taskId;
    }

    @Override
    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    @Override
    public String getProcessInstanceId() {
        return processInstanceId;
    }

View on GitHub (pinned to d6d39ce1c6)