flowable/flowable-engine · error · FlowableIllegalArgumentException
userId and groupId cannot both be null
Error message
userId and groupId cannot both be null
What it means
DeleteIdentityLinkCmd.validateParams throws FlowableIllegalArgumentException when, for a non-assignee/owner type, both userId and groupId are null. Without at least one identity, there is no link to identify and delete.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/DeleteIdentityLinkCmd.java:66
}
protected void validateParams(String userId, String groupId, String type, String taskId) {
if (taskId == null) {
throw new FlowableIllegalArgumentException("taskId is null");
}
if (type == null) {
throw new FlowableIllegalArgumentException("type is required when adding a new task identity link");
}
// Special treatment for assignee and owner: group cannot be used and userId may be null
if (IdentityLinkType.ASSIGNEE.equals(type) || IdentityLinkType.OWNER.equals(type)) {
if (groupId != null) {
throw new FlowableIllegalArgumentException("Incompatible usage: cannot use type '" + type + "' together with a groupId");
}
} else {
if (userId == null && groupId == null) {
throw new FlowableIllegalArgumentException("userId and groupId cannot both be null");
}
}
}
@Override
protected Void execute(CommandContext commandContext, TaskEntity task) {
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
if (IdentityLinkType.ASSIGNEE.equals(type)) {
TaskHelper.changeTaskAssignee(task, null, cmmnEngineConfiguration);
} else if (IdentityLinkType.OWNER.equals(type)) {
TaskHelper.changeTaskOwner(task, null, cmmnEngineConfiguration);
} else {
IdentityLinkUtil.deleteTaskIdentityLinks(task, userId, groupId, type, cmmnEngineConfiguration);
}
return null;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Provide either the userId or the groupId of the link to remove.
- Guard at the call site: require at least one non-null identity before invoking the delete.
Example fix
// before
taskService.deleteTaskIdentityLink(taskId, null, null, IdentityLinkType.CANDIDATE);
// after
if (userId == null && groupId == null) throw new IllegalArgumentException("userId or groupId required");
taskService.deleteTaskIdentityLink(taskId, userId, groupId, IdentityLinkType.CANDIDATE); Defensive patterns
Strategy: validation
Validate before calling
if (userId == null && groupId == null) throw new IllegalArgumentException("userId or groupId required"); Try / catch
try { taskService.deleteTaskIdentityLink(taskId, userId, groupId, type); } catch (FlowableIllegalArgumentException e) { log.error("Identity link delete requires userId or groupId"); } Prevention
- Require at least one identity parameter in API layers.
- Reject empty/blank strings the same as null.
When it happens
Trigger: Calling taskService.deleteTaskIdentityLink with a type like CANDIDATE but null userId and null groupId, e.g. when both came from optional request fields.
Common situations: REST/service layers with optional parameters silently forwarding nulls; cleanup jobs iterating link data where fields were never populated.
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 adding a new task identity link
- userId and groupId cannot both be null
- Job {jobId} parent is not CMMN case
- Either set the user id or the group id for an identity link,
- taskId is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/957ad3b8206da0e7.
Report an issue: GitHub.