chenhg5/cc-connect · error
config: %s.users has no roles defined
Error message
config: %s.users has no roles defined
What it means
CC-Connect requires that a project with a `[projects.users]` section defines at least one role. If `UsersConfig.Roles` is empty (the section exists but no `roles` tables are declared), validateUsersConfig rejects the config. This prevents silently deploying a project where no authorization rules apply.
Source
Thrown at config/config.go:1167
if _, ok := supportedReferenceDisplayPaths[strings.ToLower(strings.TrimSpace(rc.DisplayPath))]; !ok {
return fmt.Errorf("config: %s.references.display_path has unsupported value %q", prefix, rc.DisplayPath)
}
if _, ok := supportedReferenceMarkerStyles[strings.ToLower(strings.TrimSpace(rc.MarkerStyle))]; !ok {
return fmt.Errorf("config: %s.references.marker_style has unsupported value %q", prefix, rc.MarkerStyle)
}
if _, ok := supportedReferenceEnclosureStyles[strings.ToLower(strings.TrimSpace(rc.EnclosureStyle))]; !ok {
return fmt.Errorf("config: %s.references.enclosure_style has unsupported value %q", prefix, rc.EnclosureStyle)
}
return nil
}
// validateUsersConfig checks the [projects.users] section for consistency.
func validateUsersConfig(prefix string, u *UsersConfig) error {
if u == nil {
return nil
}
if len(u.Roles) == 0 {
return fmt.Errorf("config: %s.users has no roles defined", prefix)
}
wildcardCount := 0
seenUserIDs := make(map[string]string) // userID → role name
for roleName, rc := range u.Roles {
if len(rc.UserIDs) == 0 {
return fmt.Errorf("config: %s.users.roles.%s has empty user_ids", prefix, roleName)
}
for _, uid := range rc.UserIDs {
if uid == "*" {
wildcardCount++
continue
}
lower := strings.ToLower(uid)
if prev, dup := seenUserIDs[lower]; dup {
return fmt.Errorf("config: %s.users: user %q appears in both role %q and %q", prefix, uid, prev, roleName)
}
seenUserIDs[lower] = roleName
}View on GitHub (pinned to 4000b2338a)
Solutions
- Define at least one role with user_ids, e.g. `[[projects.myapp.users.roles]] name = "member", user_ids = ["u1"]`
- Remove the empty `[projects.<name>.users]` section entirely if per-user roles aren't needed
- Check that role blocks weren't accidentally commented out or merged away
Example fix
# before [projects.myapp.users] # after [projects.myapp.users] [projects.myapp.users.roles.member] user_ids = ["ou_1234"]
Defensive patterns
Strategy: validation
Validate before calling
if cfg.Projects[i].Users != nil && len(cfg.Projects[i].Users.Roles) == 0 {
return fmt.Errorf("project %d: users section present but no roles defined", i)
} Type guard
func hasRoles(u *UsersConfig) bool { return u != nil && len(u.Roles) > 0 } Prevention
- Don't create a [users] table until you have at least one role ready
- Check that role blocks survive comment-outs and config merges
- Scaffold new projects from config.example.toml which includes a valid role
When it happens
Trigger: Loading config.toml containing an empty `[projects.<name>.users]` table with no `[[projects.<name>.users.roles]]` entries, e.g. just `[projects.myapp.users]` with nothing under it.
Common situations: Creating the users section as a placeholder before adding roles; commenting out all role blocks while keeping the parent header; a merge/upgrade that dropped role entries.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- config: %s.users.roles.%s has empty user_ids
- no roles defined
- default_role %q does not match any defined role
- tmux: 'session' option is required (name of the tmux session
- config: relay.visibility must be "full", "summary", or "none
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/09d0f4dab9fa83df.
Report an issue: GitHub.