{"record":{"id":"829dd81391006435","repo":"flowable/flowable-engine","slug":"only-one-value-of-user-or-group-is-supported","errorCode":null,"errorMessage":"Only one value of user or group is supported.","messagePattern":"Only one value of user or group is supported\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/CaseInstanceIdentityLinkCollectionResource.java","lineNumber":80,"sourceCode":"            notes = \"Note that the groupId in Response Body will always be null, as it’s only possible to involve users with a case instance.\",\n        code = 201)\n    @ApiResponses(value = {\n            @ApiResponse(code = 201, message = \"Indicates the case instance was found and the link is created.\"),\n            @ApiResponse(code = 400, message = \"Indicates the requested body did not contain a userId or a type.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested case instance was not found.\")\n    })\n    @PostMapping(value = \"/cmmn-runtime/case-instances/{caseInstanceId}/identitylinks\", produces = \"application/json\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public RestIdentityLink createIdentityLink(@ApiParam(name = \"caseInstanceId\") @PathVariable String caseInstanceId, @RequestBody RestIdentityLink identityLink) {\n\n        CaseInstance caseInstance = getCaseInstanceFromRequestWithoutAccessCheck(caseInstanceId);\n\n        if (identityLink.getGroup() == null && identityLink.getUser() == null) {\n            throw new FlowableIllegalArgumentException(\"User or group are required.\");\n        }\n        \n        if (StringUtils.isEmpty(identityLink.getGroup()) && StringUtils.isEmpty(identityLink.getUser())) {\n            throw new FlowableIllegalArgumentException(\"Only one value of user or group is supported.\");\n        }\n\n        if (identityLink.getType() == null) {\n            throw new FlowableIllegalArgumentException(\"The identity link type is required.\");\n        }\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.createCaseInstanceIdentityLink(caseInstance, identityLink);\n        }\n\n        if (StringUtils.isNotEmpty(identityLink.getGroup())) {\n            runtimeService.addGroupIdentityLink(caseInstance.getId(), identityLink.getGroup(), identityLink.getType());\n            \n        } else {\n            runtimeService.addUserIdentityLink(caseInstance.getId(), identityLink.getUser(), identityLink.getType());\n        }\n\n        return restResponseFactory.createRestIdentityLink(identityLink.getType(), identityLink.getUser(), identityLink.getGroup(), null, null, caseInstance.getId());","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/CaseInstanceIdentityLinkCollectionResource.java#L62-L98","documentation":"When both the user and group fields of the identity link body are non-null but empty strings, FlowableIllegalArgumentException(\"Only one value of user or group is supported.\") is thrown. A case instance identity link must specify exactly one identity value: a user or a group, not both (and not two empty values).","triggerScenarios":"POST /cmmn-runtime/case-instances/{id}/identitylinks with a body where both \"user\" and \"group\" are present as empty strings (e.g. {\"user\":\"\",\"group\":\"\",\"type\":\"participant\"}) — passes the null check but fails the isEmpty check.","commonSituations":"Forms submitting empty inputs for both fields; generic serializers emitting empty strings instead of omitting fields; clients copying a payload template without clearing the unused field.","solutions":["Provide exactly one of \"user\" or \"group\" with a non-empty value and omit the other.","Convert empty strings to null/omit them in client serialization.","Validate that at least one of user/group is a non-empty string before the call."],"exampleFix":"// before\n{\"user\": \"\", \"group\": \"\", \"type\": \"participant\"}\n// after\n{\"user\": \"kermit\", \"type\": \"participant\"}","handlingStrategy":"validation","validationCode":"// Java\nboolean hasUser = StringUtils.isNotEmpty(link.getUser());\nboolean hasGroup = StringUtils.isNotEmpty(link.getGroup());\nif (hasUser == hasGroup) {\n    throw new IllegalArgumentException(\"exactly one of user or group must be non-empty\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit unused fields rather than sending empty strings","Treat empty strings as absent in client serializers","Validate exactly one of user/group is populated"],"tags":["rest-api","identity-link","validation","empty-field"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}