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
- Ensure at least one of userId or groupId is non-null before calling
- If deleting all links of a type, query the identity links first and delete them individually with their user/group ids
- 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
- Treat userId/groupId as an either-or pair in your API design
- Reject empty identity-link delete requests at the controller layer
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
- type is required when deleting a process identity link
- appDefinitionId is null
- type is required when adding a new task identity link
- identityId is null
- Either set the user id or the group id for an identity link,
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/9384ebf0c78de064.
Report an issue: GitHub.