{"record":{"id":"0cfe92ac059c5b03","repo":"chenhg5/cc-connect","slug":"no-roles-defined","errorCode":null,"errorMessage":"no roles defined","messagePattern":"no roles defined","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/user_roles.go","lineNumber":206,"sourceCode":"\t\t\t\t\"max_messages\": role.RateLimitCfg.MaxMessages,\n\t\t\t\t\"window_secs\":  int(role.RateLimitCfg.Window / time.Second),\n\t\t\t}\n\t\t}\n\t\troles[entry.roleName] = roleData\n\t}\n\n\treturn map[string]any{\n\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}","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/user_roles.go#L188-L224","documentation":"ValidateRoleInputs in core/user_roles.go rejects an empty roles list. The library requires at least one role definition when configuring project users, otherwise no role resolution could ever succeed (including the default role). It throws this before any per-role validation to fail fast.","triggerScenarios":"Calling ValidateRoleInputs with an empty (or nil) []RoleInput slice, e.g. from the handleProjectUsers HTTP handler when the client submitted a project-users payload with no roles array or an empty one.","commonSituations":"A client posts a users-config JSON with \"roles\": [] or omits the roles field entirely; a UI form was submitted without adding any role rows; a config migration dropped all roles.","solutions":["Add at least one RoleInput to the roles slice before calling ValidateRoleInputs","In handleProjectUsers, decode the request into RoleInput slice and reject empty payloads earlier with a clearer 400 message","If clearing all roles is intended, use a dedicated delete/clear API path instead of calling validation with an empty list"],"exampleFix":"// before\nerr := core.ValidateRoleInputs(cfg.DefaultRole, nil)\n// after\nif len(cfg.Roles) == 0 {\n    return errors.New(\"at least one role must be defined\")\n}\nerr := core.ValidateRoleInputs(cfg.DefaultRole, cfg.Roles)","handlingStrategy":"validation","validationCode":"if len(roles) == 0 {\n    return errors.New(\"roles must contain at least one entry\")\n}\nerr := core.ValidateRoleInputs(defaultRole, roles)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always send a non-empty roles array in project-users payloads","Validate the decoded request struct before invoking core validation","Keep a default role row in config templates"],"tags":["validation","roles","config"],"backgroundTag":"missing-required-argument","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"}