flowable/flowable-engine · error · ActivitiIllegalArgumentException

userId and groupId cannot both be null

Error message

userId and groupId cannot both be null

What it means

Parameter validation in AddIdentityLinkForProcessDefinitionCmd.validateParams: an identity link needs at least one target, so userId and groupId may not both be null (processDefinitionId null is checked in the same helper).

Solutions

  1. Provide either a userId or a groupId — at least one must be non-null
  2. Validate the input before calling; reject requests with no user and no group
  3. If removal is the goal, use the corresponding delete/remove identity link API instead

Example fix

// before
repositoryService.addGroupIdentityLinkForProcessDefinition(defId, groupId); // groupId null
// after
if (groupId == null && userId == null) {
    throw new IllegalArgumentException("Provide userId or groupId");
}
repositoryService.addGroupIdentityLinkForProcessDefinition(defId, groupId);
Defensive patterns

Strategy: validation

Validate before calling

if (userId == null && groupId == null) {
    throw new IllegalArgumentException("At least one of userId or groupId must be provided");
}

Try / catch

try {
    repositoryService.addIdentityLinkForProcessDefinition(defId, userId, groupId, type);
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("both be null")) {
        // reject or supply a default group
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling repositoryService.addUserIdentityLinkForProcessDefinition(id, null) (userId overload with null) or constructing the command with both userId and groupId null.

Common situations: Both user and group variables were resolved from empty configuration or a form with unfilled fields; a refactor removed the default group id; intending to delete a link but using the add command.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/AddIdentityLinkForProcessDefinitionCmd.java:50

    protected String userId;

    protected String groupId;

    public AddIdentityLinkForProcessDefinitionCmd(String processDefinitionId, String userId, String groupId) {
        validateParams(userId, groupId, processDefinitionId);
        this.processDefinitionId = processDefinitionId;
        this.userId = userId;
        this.groupId = groupId;
    }

    protected void validateParams(String userId, String groupId, String processDefinitionId) {
        if (processDefinitionId == null) {
            throw new ActivitiIllegalArgumentException("processDefinitionId is null");
        }

        if (userId == null && groupId == null) {
            throw new ActivitiIllegalArgumentException("userId and groupId cannot both be null");
        }
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ProcessDefinitionEntity processDefinition = commandContext
                .getProcessDefinitionEntityManager()
                .findProcessDefinitionById(processDefinitionId);

        if (processDefinition == null) {
            throw new ActivitiObjectNotFoundException("Cannot find process definition with id " + processDefinitionId, ProcessDefinition.class);
        }

        processDefinition.addIdentityLink(userId, groupId);

        return null;
    }

View on GitHub (pinned to d6d39ce1c6)