{"record":{"id":"f88d4c026a6c83c0","repo":"chenhg5/cc-connect","slug":"role-q-has-empty-user-ids","errorCode":null,"errorMessage":"role %q has empty user_ids","messagePattern":"role %q has empty user_ids","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/user_roles.go","lineNumber":214,"sourceCode":"\t\t\"configured\":   true,\n\t\t\"default_role\": m.defaultRole,\n\t\t\"roles\":        roles,\n\t}\n}\n\n// ValidateRoleInputs checks role inputs for consistency: duplicate user IDs,\n// multiple wildcards, empty user_ids, and default_role existence.\nfunc ValidateRoleInputs(defaultRole string, roles []RoleInput) error {\n\tif len(roles) == 0 {\n\t\treturn fmt.Errorf(\"no roles defined\")\n\t}\n\twildcardCount := 0\n\tseenUserIDs := make(map[string]string) // userID → role name\n\troleNames := make(map[string]bool, len(roles))\n\tfor _, ri := range roles {\n\t\troleNames[ri.Name] = true\n\t\tif len(ri.UserIDs) == 0 {\n\t\t\treturn fmt.Errorf(\"role %q has empty user_ids\", ri.Name)\n\t\t}\n\t\tfor _, uid := range ri.UserIDs {\n\t\t\tif uid == \"*\" {\n\t\t\t\twildcardCount++\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlower := strings.ToLower(uid)\n\t\t\tif prev, dup := seenUserIDs[lower]; dup {\n\t\t\t\treturn fmt.Errorf(\"user %q appears in both role %q and %q\", uid, prev, ri.Name)\n\t\t\t}\n\t\t\tseenUserIDs[lower] = ri.Name\n\t\t}\n\t}\n\tif wildcardCount > 1 {\n\t\treturn fmt.Errorf(\"wildcard user_ids=[\\\"*\\\"] appears in multiple roles\")\n\t}\n\tif defaultRole != \"\" {\n\t\tif !roleNames[defaultRole] {","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/user_roles.go#L196-L232","documentation":"ValidateRoleInputs rejects a role entry whose UserIDs list is empty. Every defined role must name at least one user (or the \"*\" wildcard) to be meaningful for authorization. The error names the offending role so the misconfiguration is easy to locate.","triggerScenarios":"Passing a RoleInput with Name set (e.g. \"admin\") but UserIDs nil or len 0 to ValidateRoleInputs, typically via the handleProjectUsers handler when a role block in the request JSON has an empty user_ids array.","commonSituations":"A hand-edited TOML/JSON project config where a role was created but users were never filled in; a UI that allows saving a role with no members; a template with a placeholder role left unfilled.","solutions":["Populate UserIDs for the named role before validation","Delete the empty role entry entirely if it is not needed","Add client-side/server-side validation to reject role rows with no users before calling ValidateRoleInputs"],"exampleFix":"// before\nroles := []core.RoleInput{{Name: \"admin\"}}\n// after\nroles := []core.RoleInput{{Name: \"admin\", UserIDs: []string{\"alice\"}}}","handlingStrategy":"validation","validationCode":"for _, r := range roles {\n    if len(r.UserIDs) == 0 {\n        return fmt.Errorf(\"role %q needs at least one user\", r.Name)\n    }\n}\ncore.ValidateRoleInputs(defaultRole, roles)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never persist a role with an empty user_ids list","Enforce required-user field in UI forms","Audit configs for placeholder roles before deploy"],"tags":["validation","roles","empty-array"],"backgroundTag":"empty-required-field","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}