{"record":{"id":"41a638a36c8763ce","repo":"flowable/flowable-engine","slug":"userid-cannot-be-null-41a638","errorCode":null,"errorMessage":"UserId cannot be null.","messagePattern":"UserId cannot be null\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/identity/GroupMembershipCollectionResource.java","lineNumber":54,"sourceCode":"@RestController\n@Api(tags = { \"Groups\" }, authorizations = { @Authorization(value = \"basicAuth\") })\npublic class GroupMembershipCollectionResource extends BaseGroupResource {\n\n    @ApiOperation(value = \"Add a member to a group\", tags = { \"Groups\" }, code = 201)\n    @ApiResponses(value = {\n            @ApiResponse(code = 201, message = \"Indicates the group was found and the member has been added.\"),\n            @ApiResponse(code = 400, message = \"Indicates the userId was not included in the request body.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested group was not found.\"),\n            @ApiResponse(code = 409, message = \"Indicates the requested user is already a member of the group.\")\n    })\n    @PostMapping(value = \"/identity/groups/{groupId}/members\", produces = \"application/json\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public MembershipResponse createMembership(@ApiParam(name = \"groupId\") @PathVariable String groupId, @RequestBody MembershipRequest memberShip) {\n\n        Group group = getGroupFromRequest(groupId);\n\n        if (memberShip.getUserId() == null) {\n            throw new FlowableIllegalArgumentException(\"UserId cannot be null.\");\n        }\n\n        // Check if user is member of group since API does not return typed exception\n        if (identityService.createUserQuery().memberOfGroup(group.getId()).userId(memberShip.getUserId()).count() > 0) {\n            throw new FlowableConflictException(\"User '\" + memberShip.getUserId() + \"' is already part of group '\" + group.getId() + \"'.\");\n        }\n\n        identityService.createMembership(memberShip.getUserId(), group.getId());\n\n        return restResponseFactory.createMembershipResponse(memberShip.getUserId(), group.getId());\n    }\n}\n","sourceCodeStart":36,"sourceCodeEnd":67,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/identity/GroupMembershipCollectionResource.java#L36-L67","documentation":"GroupMembershipCollectionResource.createMembership validates MembershipRequest.userId before creating the membership. A null userId throws FlowableIllegalArgumentException (HTTP 400) because identityService.createMembership requires both a user id and a group id.","triggerScenarios":"POST /identity/groups/{groupId}/members with a body missing \"userId\", e.g. {\"userId\":null} or {}.","commonSituations":"Client form field never filled in; JSON property name mismatch (memberId/user vs userId) so Jackson binds null; automated script building the payload from a variable that is null.","solutions":["Include a non-null \"userId\" in the request body.","Fix client serialization so the user identifier maps to the \"userId\" property.","Validate the payload client-side before the POST."],"exampleFix":"// before\nPOST /identity/groups/sales/members {\"user\":\"jdoe\"}\n// after\nPOST /identity/groups/sales/members {\"userId\":\"jdoe\"}","handlingStrategy":"validation","validationCode":"if (member == null || member.getUserId() == null || member.getUserId().isBlank()) {\n    throw new IllegalArgumentException(\"userId is required for group membership\");\n}","typeGuard":"boolean hasUserId(MembershipRequest r) { return r != null && r.getUserId() != null && !r.getUserId().isEmpty(); }","tryCatchPattern":null,"preventionTips":["Use the exact JSON property \"userId\".","Ensure UI forms require a selected user before submit.","Guard scripts against null user variables."],"tags":["rest-api","validation","membership","bad-request"],"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"}