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

  1. Define at least one role with user_ids, e.g. `[[projects.myapp.users.roles]] name = "member", user_ids = ["u1"]`
  2. Remove the empty `[projects.<name>.users]` section entirely if per-user roles aren't needed
  3. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/09d0f4dab9fa83df. Report an issue: GitHub.