flowable/flowable-engine · error · ActivitiIllegalArgumentException
type is required when adding a new task identity link
Error message
type is required when adding a new task identity link
What it means
AddIdentityLinkCmd adds an identity link (user/group association) to a task. Before executing, validateParams checks that the identity link 'type' (e.g. assignee, candidate, owner) is non-null. Flowable throws ActivitiIllegalArgumentException because an identity link without a type is meaningless and cannot be persisted.
Solutions
- Pass a valid IdentityLinkType constant (ASSIGNEE, OWNER, CANDIDATE, PARTICIPANT) as the type argument
- Check the type variable for null before calling addIdentityLink
- If the type comes from external input, default to IdentityLinkType.CANDIDATE or reject the request early
Example fix
// before taskService.addUserIdentityLink(taskId, userId, linkType); // linkType is null // after String type = linkType != null ? linkType : IdentityLinkType.CANDIDATE; taskService.addUserIdentityLink(taskId, userId, type);
Defensive patterns
Strategy: validation
Validate before calling
if (taskId == null || linkType == null) {
throw new IllegalArgumentException("taskId and linkType are required");
} Try / catch
try {
taskService.addUserIdentityLink(taskId, userId, linkType);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("type is required")) {
taskService.addUserIdentityLink(taskId, userId, IdentityLinkType.CANDIDATE);
} else { throw e; }
} Prevention
- Always use IdentityLinkType constants instead of raw strings
- Null-check optional inputs before invoking engine commands
- Validate at the API/service boundary before reaching the engine
When it happens
Trigger: Calling taskService.addUserIdentityLink(taskId, userId, null), taskService.addGroupIdentityLink with a null type, or constructing AddIdentityLinkCmd directly with type == null.
Common situations: Passing a variable holding the link type that was never initialized; reading the type from config/JSON where the key is missing; confusion between identityId and identityType parameters due to similar names.
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
- identityId is null
- taskId is null
- appDefinitionId is null
- identityId is null
- processDefinitionId is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2b38b0bc862665cc.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/AddIdentityLinkCmd.java:51
protected String identityType;
public AddIdentityLinkCmd(String taskId, String identityId, int identityIdType, String identityType) {
super(taskId);
validateParams(taskId, identityId, identityIdType, identityType);
this.taskId = taskId;
this.identityId = identityId;
this.identityIdType = identityIdType;
this.identityType = identityType;
}
protected void validateParams(String taskId, String identityId, int identityIdType, String identityType) {
if (taskId == null) {
throw new ActivitiIllegalArgumentException("taskId is null");
}
if (identityType == null) {
throw new ActivitiIllegalArgumentException("type is required when adding a new task identity link");
}
if (identityId == null && (identityIdType == IDENTITY_GROUP ||
(!IdentityLinkType.ASSIGNEE.equals(identityType) && !IdentityLinkType.OWNER.equals(identityType)))) {
throw new ActivitiIllegalArgumentException("identityId is null");
}
if (identityIdType != IDENTITY_USER && identityIdType != IDENTITY_GROUP) {
throw new ActivitiIllegalArgumentException("identityIdType allowed values are 1 and 2");
}
}
@Override
protected Void execute(CommandContext commandContext, TaskEntity task) {
boolean assignedToNoOne = false;
if (IdentityLinkType.ASSIGNEE.equals(identityType)) {View on GitHub (pinned to d6d39ce1c6)