flowable/flowable-engine · error · ActivitiIllegalArgumentException
userId and groupId cannot both be null
Error message
userId and groupId cannot both be null
What it means
When deleting an identity link from a process definition, exactly which link must be removed is determined by userId and/or groupId. If both are null, validateParams throws ActivitiIllegalArgumentException because the deletion target is undefined.
Solutions
- Pass the userId or groupId used when the identity link was added (addProcessDefinitionIdentityLink).
- Validate at the call site that at least one identifier is present before deleting.
- Log/inspect ACT_RE_PROCDEF identity links (or use repositoryService.getIdentityLinksForProcessDefinition) to find the exact stored identifier.
Example fix
// before repositoryService.deleteProcessDefinitionIdentityLink(defId, userId, groupId); // both null // after repositoryService.deleteProcessDefinitionIdentityLink(defId, null, "sales");
Defensive patterns
Strategy: validation
Validate before calling
if (userId == null && groupId == null) {
throw new IllegalArgumentException("Provide userId or groupId for process definition identity link deletion");
} Try / catch
try {
repositoryService.deleteCandidateStarterGroup(defId, groupId);
} catch (ActivitiIllegalArgumentException e) {
log.warn("No identity given: {}", e.getMessage());
} Prevention
- List current links with repositoryService.getIdentityLinksForProcessDefinition(defId) to find stored identifiers
- Make user/group fields mandatory in admin tooling that manages candidate starters
- Keep add/delete calls symmetric: same identifier values on both sides
When it happens
Trigger: Calling deleteProcessDefinitionIdentityLink(processDefinitionId, null, null) or the candidate-starter variants with a null identifier argument.
Common situations: Generic authorization-management screens where the user/group field was left empty; configuration-driven cleanup where the group name was missing from config; code copying add-identity-link validation but inverting parameter order.
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
- processDefinitionId is null
- processDefinitionId is null
- userId and groupId cannot both be null
- appDefinitionId is null
- identityId is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d58278f2f094222d.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteIdentityLinkForProcessDefinitionCmd.java:51
protected String userId;
protected String groupId;
public DeleteIdentityLinkForProcessDefinitionCmd(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.deleteIdentityLink(userId, groupId);
return null;
}
View on GitHub (pinned to d6d39ce1c6)