{"record":{"id":"fb12cb25d83978af","repo":"weaviate/weaviate","slug":"roles-can-not-be-empty","errorCode":null,"errorMessage":"roles can not be empty","messagePattern":"roles can not be empty","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"adapters/handlers/rest/authz/handlers_authz.go","lineNumber":812,"sourceCode":"\t\tif strings.TrimSpace(role) == \"\" {\n\t\t\treturn authz.NewAssignRoleToUserBadRequest().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, fmt.Errorf(\"one or more of the roles you want to assign is empty\")))\n\t\t}\n\n\t\tif err := validateEnvVarRoles(role); err != nil {\n\t\t\treturn authz.NewAssignRoleToUserForbidden().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, fmt.Errorf(\"assigning: %w\", err)))\n\t\t}\n\t}\n\n\tif err := h.validateUserIDForNamespaces(internalID); err != nil {\n\t\treturn authz.NewAssignRoleToUserBadRequest().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, err))\n\t}\n\n\tif err := h.validateUserTypeForNamespaces(params.Body.UserType); err != nil {\n\t\treturn authz.NewAssignRoleToUserBadRequest().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, err))\n\t}\n\n\tif len(params.Body.Roles) == 0 {\n\t\treturn authz.NewAssignRoleToUserBadRequest().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, fmt.Errorf(\"roles can not be empty\")))\n\t}\n\n\tif err := h.authorizer.Authorize(ctx, principal, authorization.USER_AND_GROUP_ASSIGN_AND_REVOKE, authorization.Users(internalID)...); err != nil {\n\t\treturn authz.NewAssignRoleToUserForbidden().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, err))\n\t}\n\n\troleNames, notFound, err := h.resolveAssignableRoles(principal, params.Body.Roles)\n\tif notFound {\n\t\treturn authz.NewAssignRoleToUserNotFound().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, fmt.Errorf(\"one or more of the roles requested doesn't exist\")))\n\t}\n\tif err != nil {\n\t\treturn authz.NewAssignRoleToUserBadRequest().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, err))\n\t}\n\n\tif err := h.validateLocalRoleAssignment(principal, roleNames); err != nil {\n\t\treturn authz.NewAssignRoleToUserForbidden().WithPayload(cerrors.ErrPayloadFromSingleErr(principal, err))\n\t}\n","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/adapters/handlers/rest/authz/handlers_authz.go#L794-L830","documentation":"A 400 Bad Request returned when the assign-roles request body contains an empty Roles array (len == 0). The handler checks this after namespace/user-type validation but before authorization and role resolution. Assigning zero roles is considered a malformed request rather than a no-op.","triggerScenarios":"POST /v1/users/{userId}/roles/assign with body {\"roles\": []} (or roles omitted/null) and a valid UserType — the empty list check at handlers_authz.go:812 fires.","commonSituations":"Clients serializing an empty Go/JS slice into the request body; frontend that sends the assign call even when no checkboxes are selected; code paths that build the roles list dynamically and end up empty (e.g. after filtering out invalid roles).","solutions":["Ensure the roles array has at least one non-empty role name before calling the API","If the intent is to remove all roles, use the revoke-roles endpoint instead of assigning an empty list","Add a client-side guard that skips the call when the roles list is empty"],"exampleFix":"// before\nif len(roles) == 0 { roles = []string{} }\nclient.Users().Assigner().WithUser(id).WithRoles(roles...).Do(ctx)\n// after\nif len(roles) == 0 {\n    return nil // or use the revoke endpoint; do not call assign with empty list\n}\nclient.Users().Assigner().WithUser(id).WithRoles(roles...).Do(ctx)","handlingStrategy":"validation","validationCode":"if len(roles) == 0 {\n    return errors.New(\"refusing to assign empty roles list; use revoke endpoint to remove roles\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard the call site: skip assignment entirely when the roles slice is empty","Use the revoke endpoint (POST /v1/users/{id}/roles/revoke) to remove roles, never assign-with-empty","Filter invalid roles before assignment and abort if nothing remains"],"tags":["rbac","validation","bad-request","rest-api","weaviate"],"backgroundTag":"empty-roles-list","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}