flowable/flowable-engine · error · ActivitiException

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

Mirror of setUserId: a historic identity link is either a user assignment or a group assignment. setGroupId throws when a userId is already set and a non-null groupId is assigned, preventing a single row from representing both.

Solutions

  1. Use a fresh entity for the group assignment.
  2. Set userId to null first if the link must become group-based.
  3. Model candidate user + candidate group as two separate identity link records.

Example fix

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

// after
link.setUserId("kermit");
HistoricIdentityLinkEntity groupLink = ...; groupLink.setGroupId("management");
Defensive patterns

Strategy: type-guard

Validate before calling

if (link.getUserId() != null && groupId != null) {
    throw new IllegalArgumentException("link already user-based");
}

Type guard

function canSetGroupId(link) {
  return link.getUserId() == null;
}

Try / catch

try {
    link.setGroupId(groupId);
} catch (ActivitiException e) {
    link = createNewIdentityLink();
    link.setGroupId(groupId);
}

Prevention

When it happens

Trigger: Calling setGroupId on a HistoricIdentityLinkEntity whose userId is already non-null with a non-null groupId.

Common situations: Same as the userId variant: entity reuse in custom history handling, migration scripts, or event listeners copying assignment data without clearing the prior field.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/HistoricIdentityLinkEntity.java:127

    public String getUserId() {
        return userId;
    }

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

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

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

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

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

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

View on GitHub (pinned to d6d39ce1c6)