flowable/flowable-engine · error · FlowableIllegalArgumentException
Only one of user or group can be used to create an identity…
Error message
Only one of user or group can be used to create an identity link.
What it means
The Flowable CMMN REST API rejects an identity link creation request when the payload specifies both a user and a group. An identity link associates exactly one principal (a user OR a group) with a task, so a request carrying both is ambiguous and cannot be represented.
Solutions
- Remove the 'user' or the 'group' field from the request body so exactly one is set
- If the intent is a user link, set only {"user": "...", "type": "candidate"}; for a group link set only {"group": "...", "type": "candidate"}
- Fix client-side serialization so mutually exclusive principals never both appear in the payload
Example fix
// before
POST /cmmn-runtime/tasks/123/identitylinks
{"user":"john","group":"management","type":"candidate"}
// after
POST /cmmn-runtime/tasks/123/identitylinks
{"group":"management","type":"candidate"} Defensive patterns
Strategy: validation
Validate before calling
function canCreateIdentityLink(body) {
const count = [body.user, body.group].filter(Boolean).length;
return count === 1 && typeof body.type === 'string';
} Type guard
function hasExactlyOnePrincipal(b) {
return (b.user != null) !== (b.group != null);
} Try / catch
try {
await post(`/cmmn-runtime/tasks/${taskId}/identitylinks`, body);
} catch (e) {
if (e.status === 400 && /Only one of user or group/.test(e.body.message)) {
throw new Error('Send either user or group, not both');
}
throw e;
} Prevention
- Model the payload with a discriminated union: either {user} or {group}, never both
- Clear the sibling field when one principal is chosen in UI code
- Unit-test request serialization with both fields set to catch regressions
When it happens
Trigger: POSTing to /cmmn-runtime/tasks/{taskId}/identitylinks with a JSON body where both 'user' and 'group' fields are non-null.
Common situations: Client code copies an object with both fields populated; a form collects both assignee-user and candidate-group and serializes them together; a generic 'owner' object is mapped into the request body without picking one principal.
Related errors
- A group or a user is required to create an identity link.
- Identity link family should be 'users' or 'groups'.
- IdentityId is required.
- Only one of user or group can be used to create an identity…
- Only one value of user or group is supported.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/3eebadb33431cfdd.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskIdentityLinkCollectionResource.java:76
@ApiOperation(value = "Create an identity link on a task", tags = { "Task Identity Links" }, nickname = "createTaskInstanceIdentityLinks",
notes = "It is possible to add either a user or a group.", code = 201)
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Indicates the task was found and the identity link was created."),
@ApiResponse(code = 404, message = "Indicates the requested task was not found or the task does not have the requested identityLink. The status contains additional information about this error.")
})
@PostMapping(value = "/cmmn-runtime/tasks/{taskId}/identitylinks", produces = "application/json")
@ResponseStatus(HttpStatus.CREATED)
public RestIdentityLink createIdentityLink(@ApiParam(name = "taskId") @PathVariable("taskId") String taskId, @RequestBody RestIdentityLink identityLink) {
Task task = getTaskFromRequestWithoutAccessCheck(taskId);
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 (identityLink.getType() == null) {
throw new FlowableIllegalArgumentException("The identity link type is required.");
}
if (restApiInterceptor != null) {
restApiInterceptor.createTaskIdentityLink(task, identityLink);
}
if (identityLink.getGroup() != null) {
taskService.addGroupIdentityLink(task.getId(), identityLink.getGroup(), identityLink.getType());
} else {
taskService.addUserIdentityLink(task.getId(), identityLink.getUser(), identityLink.getType());
}
return restResponseFactory.createRestIdentityLink(identityLink.getType(), identityLink.getUser(), identityLink.getGroup(), task.getId(), null, null);
}View on GitHub (pinned to d6d39ce1c6)