flowable/flowable-engine · error · FlowableIllegalArgumentException
A group or a user is required to create an identity link.
Error message
A group or a user is required to create an identity link.
What it means
Thrown when creating an identity link on a process definition (POST /repository/process-definitions/{processDefinitionId}/identitylinks) when the request body specifies neither a group nor a user. An identity link must associate the definition with at least one of the two.
Solutions
- Include either "user":"<userId>" or "group":"<groupId>" in the request body
- Validate the body before sending (only one of user/group set, type provided)
- If you meant a candidate-starter for a group, set the group field instead of leaving both blank
Example fix
// before
{"type":"candidate"}
// after
{"type":"candidate","group":"sales"} Defensive patterns
Strategy: validation
Validate before calling
if (body.getGroup() == null && body.getUser() == null) throw new IllegalArgumentException("identity link needs a user or a group"); Try / catch
try { createIdentityLink(defId, link); } catch (FlowableIllegalArgumentException e) { /* prompt user to pick a user or group */ } Prevention
- Validate the JSON body before POSTing
- Require users/groups to be explicitly selected in UIs
- Cover user/group/none cases in API client tests
When it happens
Trigger: POST identity link with a JSON body where both 'user' and 'group' are null/missing, e.g. {"type":"candidate"} only.
Common situations: Clients omitting fields when generalizing user/group link code; templates with unfilled placeholders; payload built dynamically where both variables end up null.
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
- Only one of user or group can be used to create an identity…
- A group or a user is required to create an identity link.
- A group or a user is required to create an identity link.
- Comment text is required.
- Either processDefinitionId, processDefinitionKey or message…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2ec87b59e6894e57.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionIdentityLinkCollectionResource.java:75
return restResponseFactory.createRestIdentityLinks(repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId()));
}
@ApiOperation(value = "Add a candidate starter to a process definition", tags = { "Process Definitions" },
notes = "It is possible to add either a user or a group.",
code = 201)
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Indicates the process definition was found and the identity link was created."),
@ApiResponse(code = 400, message = "Indicates the body does not contain the correct information."),
@ApiResponse(code = 404, message = "Indicates the requested process definition was not found.")
})
@PostMapping(value = "/repository/process-definitions/{processDefinitionId}/identitylinks", produces = "application/json")
@ResponseStatus(HttpStatus.CREATED)
public RestIdentityLink createIdentityLink(@ApiParam(name = "processDefinitionId") @PathVariable String processDefinitionId, @RequestBody RestIdentityLink identityLink) {
ProcessDefinition processDefinition = getProcessDefinitionFromRequestWithoutAccessCheck(processDefinitionId);
if (identityLink.getGroup() == null && identityLink.getUser() == null) {
throw new FlowableIllegalArgumentException("A group or a user is required to create an identity link.");
}
if (identityLink.getGroup() != null && identityLink.getUser() != null) {
throw new FlowableIllegalArgumentException("Only one of user or group can be used to create an identity link.");
}
if (restApiInterceptor != null) {
restApiInterceptor.createProcessDefinitionIdentityLink(processDefinition, identityLink);
}
if (identityLink.getGroup() != null) {
repositoryService.addCandidateStarterGroup(processDefinition.getId(), identityLink.getGroup());
} else {
repositoryService.addCandidateStarterUser(processDefinition.getId(), identityLink.getUser());
}
// Always candidate for process-definition. User-provided value is
// ignoredView on GitHub (pinned to d6d39ce1c6)