{"record":{"id":"2c3b5453b742d0a6","repo":"chenhg5/cc-connect","slug":"config-s-users-roles-s-has-empty-user-ids","errorCode":null,"errorMessage":"config: %s.users.roles.%s has empty user_ids","messagePattern":"config: (.+?)\\.users\\.roles\\.(.+?) has empty user_ids","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/config.go","lineNumber":1173,"sourceCode":"\tif _, ok := supportedReferenceEnclosureStyles[strings.ToLower(strings.TrimSpace(rc.EnclosureStyle))]; !ok {\n\t\treturn fmt.Errorf(\"config: %s.references.enclosure_style has unsupported value %q\", prefix, rc.EnclosureStyle)\n\t}\n\treturn nil\n}\n\n// validateUsersConfig checks the [projects.users] section for consistency.\nfunc validateUsersConfig(prefix string, u *UsersConfig) error {\n\tif u == nil {\n\t\treturn nil\n\t}\n\tif len(u.Roles) == 0 {\n\t\treturn fmt.Errorf(\"config: %s.users has no roles defined\", prefix)\n\t}\n\twildcardCount := 0\n\tseenUserIDs := make(map[string]string) // userID → role name\n\tfor roleName, rc := range u.Roles {\n\t\tif len(rc.UserIDs) == 0 {\n\t\t\treturn fmt.Errorf(\"config: %s.users.roles.%s has empty user_ids\", prefix, roleName)\n\t\t}\n\t\tfor _, uid := range rc.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(\"config: %s.users: user %q appears in both role %q and %q\", prefix, uid, prev, roleName)\n\t\t\t}\n\t\t\tseenUserIDs[lower] = roleName\n\t\t}\n\t}\n\tif wildcardCount > 1 {\n\t\treturn fmt.Errorf(\"config: %s.users: wildcard user_ids=[\\\"*\\\"] appears in multiple roles\", prefix)\n\t}\n\tif u.DefaultRole != \"\" {\n\t\tif _, ok := u.Roles[u.DefaultRole]; !ok {","sourceCodeStart":1155,"sourceCodeEnd":1191,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/config/config.go#L1155-L1191","documentation":"CC-Connect requires every role under `[projects.users.roles]` to list at least one user ID. If a role's `user_ids` array is empty or missing, validateUsersConfig rejects the config, naming the project prefix and role name. This catches roles that would never match any user.","triggerScenarios":"Loading config.toml where a role table declares no user_ids, e.g. `[projects.myapp.users.roles.admins]` with `user_ids = []` or the key omitted entirely.","commonSituations":"Adding a role as a stub before assigning members; a role whose members were all removed; renaming a role but leaving the old empty block behind.","solutions":["Add at least one user ID to the role's user_ids array","Use \"*\" in user_ids to match all users if the role should be a catch-all","Delete the empty role block if it's no longer needed"],"exampleFix":"# before\n[projects.myapp.users.roles.admins]\nuser_ids = []\n\n# after\n[projects.myapp.users.roles.admins]\nuser_ids = [\"ou_1234\", \"ou_5678\"]","handlingStrategy":"validation","validationCode":"for name, role := range cfg.Projects[i].Users.Roles {\n    if len(role.UserIDs) == 0 {\n        return fmt.Errorf(\"role %q has empty user_ids\", name)\n    }\n}","typeGuard":"func roleHasMembers(rc RoleConfig) bool { return len(rc.UserIDs) > 0 }","tryCatchPattern":null,"preventionTips":["Never commit role stubs with empty user_ids; add members or remove the block","Use \"*\" for a catch-all role instead of leaving it empty","Review [users.roles] blocks during config review before deploying"],"tags":["config","validation","users","roles"],"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-14T05:17:10.506Z"}