{"record":{"id":"2ec87b59e6894e57","repo":"flowable/flowable-engine","slug":"a-group-or-a-user-is-required-to-create-an-identit-2ec87b","errorCode":null,"errorMessage":"A group or a user is required to create an identity link.","messagePattern":"A group or a user is required to create an identity link\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionIdentityLinkCollectionResource.java","lineNumber":75,"sourceCode":"        return restResponseFactory.createRestIdentityLinks(repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId()));\n    }\n\n    @ApiOperation(value = \"Add a candidate starter to a process definition\", tags = { \"Process Definitions\" },\n            notes = \"It is possible to add either a user or a group.\",\n            code = 201)\n    @ApiResponses(value = {\n            @ApiResponse(code = 201, message = \"Indicates the process definition was found and the identity link was created.\"),\n            @ApiResponse(code = 400, message = \"Indicates the body does not contain the correct information.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested process definition was not found.\")\n    })\n    @PostMapping(value = \"/repository/process-definitions/{processDefinitionId}/identitylinks\", produces = \"application/json\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public RestIdentityLink createIdentityLink(@ApiParam(name = \"processDefinitionId\") @PathVariable String processDefinitionId, @RequestBody RestIdentityLink identityLink) {\n\n        ProcessDefinition processDefinition = getProcessDefinitionFromRequestWithoutAccessCheck(processDefinitionId);\n\n        if (identityLink.getGroup() == null && identityLink.getUser() == null) {\n            throw new FlowableIllegalArgumentException(\"A group or a user is required to create an identity link.\");\n        }\n\n        if (identityLink.getGroup() != null && identityLink.getUser() != null) {\n            throw new FlowableIllegalArgumentException(\"Only one of user or group can be used to create an identity link.\");\n        }\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.createProcessDefinitionIdentityLink(processDefinition, identityLink);\n        }\n\n        if (identityLink.getGroup() != null) {\n            repositoryService.addCandidateStarterGroup(processDefinition.getId(), identityLink.getGroup());\n        } else {\n            repositoryService.addCandidateStarterUser(processDefinition.getId(), identityLink.getUser());\n        }\n\n        // Always candidate for process-definition. User-provided value is\n        // ignored","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/ProcessDefinitionIdentityLinkCollectionResource.java#L57-L93","documentation":"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.","triggerScenarios":"POST identity link with a JSON body where both 'user' and 'group' are null/missing, e.g. {\"type\":\"candidate\"} only.","commonSituations":"Clients omitting fields when generalizing user/group link code; templates with unfilled placeholders; payload built dynamically where both variables end up null.","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"],"exampleFix":"// before\n{\"type\":\"candidate\"}\n// after\n{\"type\":\"candidate\",\"group\":\"sales\"}","handlingStrategy":"validation","validationCode":"if (body.getGroup() == null && body.getUser() == null) throw new IllegalArgumentException(\"identity link needs a user or a group\");","typeGuard":null,"tryCatchPattern":"try { createIdentityLink(defId, link); } catch (FlowableIllegalArgumentException e) { /* prompt user to pick a user or group */ }","preventionTips":["Validate the JSON body before POSTing","Require users/groups to be explicitly selected in UIs","Cover user/group/none cases in API client tests"],"tags":["flowable","rest","identity-link","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}