flowable/flowable-engine · error · FlowableIllegalArgumentException

userId and groupId cannot both be null

Error message

userId and groupId cannot both be null

What it means

FlowableIllegalArgumentException thrown by DeleteIdentityLinkForCaseInstanceCmd.validateParams when both userId and groupId are null. Deleting an identity link requires at least one of the two so the engine knows which link to remove. This is an argument-completeness guard.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/DeleteIdentityLinkForCaseInstanceCmd.java:60

        
        validateParams(userId, groupId, caseInstanceId, type);
        this.caseInstanceId = caseInstanceId;
        this.userId = userId;
        this.groupId = groupId;
        this.type = type;
    }

    protected void validateParams(String userId, String groupId, String caseInstanceId, String type) {
        if (caseInstanceId == null) {
            throw new FlowableIllegalArgumentException("caseInstanceId is null");
        }

        if (type == null) {
            throw new FlowableIllegalArgumentException("type is required when deleting a process identity link");
        }

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

    @Override
    public Void execute(CommandContext commandContext) {
        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        CaseInstance caseInstance = cmmnEngineConfiguration.getCaseInstanceEntityManager().findById(caseInstanceId);

        if (caseInstance == null) {
            throw new FlowableObjectNotFoundException("Cannot find case instance with id " + caseInstanceId, CaseInstanceEntity.class);
        }

        IdentityLinkUtil.deleteCaseInstanceIdentityLinks(caseInstance, userId, groupId, type, cmmnEngineConfiguration);
        
        return null;
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure at least one of userId or groupId is non-null before calling
  2. If deleting all links of a type, query the identity links first and delete them individually with their user/group ids
  3. Reject empty requests in your own API layer before reaching the engine

Example fix

// before
caseService.deleteCaseInstanceIdentityLink(caseInstanceId, userId, groupId, type); // both null
// after
if (userId == null && groupId == null) {
    throw new IllegalArgumentException("Provide userId or groupId");
}
caseService.deleteCaseInstanceIdentityLink(caseInstanceId, userId, groupId, type);
Defensive patterns

Strategy: validation

Validate before calling

if (userId == null && groupId == null) throw new IllegalArgumentException("userId or groupId required");

Type guard

boolean hasSubject = userId != null || groupId != null;

Prevention

When it happens

Trigger: Calling deleteCaseInstanceIdentityLink(caseInstanceId, null, null, type) with no user and no group identified.

Common situations: Generic delete buttons in apps that clear both user and group fields; deserialization of an empty request body where neither field was populated; code that computed one of the two but both came back empty.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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