chenhg5/cc-connect · error

wildcard user_ids=["*"] appears in multiple roles

Error message

wildcard user_ids=["*"] appears in multiple roles

What it means

ValidateRoleInputs allows the wildcard user_ids=["*"] in only one role, because a wildcard matches every user and two wildcards would make role resolution ambiguous. It counts wildcard occurrences and rejects the config when more than one role contains "*".

Source

Thrown at core/user_roles.go:229

	for _, ri := range roles {
		roleNames[ri.Name] = true
		if len(ri.UserIDs) == 0 {
			return fmt.Errorf("role %q has empty user_ids", ri.Name)
		}
		for _, uid := range ri.UserIDs {
			if uid == "*" {
				wildcardCount++
				continue
			}
			lower := strings.ToLower(uid)
			if prev, dup := seenUserIDs[lower]; dup {
				return fmt.Errorf("user %q appears in both role %q and %q", uid, prev, ri.Name)
			}
			seenUserIDs[lower] = ri.Name
		}
	}
	if wildcardCount > 1 {
		return fmt.Errorf("wildcard user_ids=[\"*\"] appears in multiple roles")
	}
	if defaultRole != "" {
		if !roleNames[defaultRole] {
			return fmt.Errorf("default_role %q does not match any defined role", defaultRole)
		}
	}
	return nil
}

// Stop terminates all per-role rate limiter goroutines. Nil-receiver safe.
func (m *UserRoleManager) Stop() {
	if m == nil {
		return
	}
	m.mu.Lock()
	defer m.mu.Unlock()
	for _, rl := range m.limiters {
		rl.Stop()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Keep "*" in exactly one role (usually the lowest-privilege fallback) and list concrete user IDs in the others
  2. Merge the two wildcard roles into one
  3. If the intent is tiered defaults, model that with role ordering/priority instead of multiple wildcards

Example fix

// before
roles := []core.RoleInput{
    {Name: "admin", UserIDs: []string{"*"}},
    {Name: "dev", UserIDs: []string{"*"}},
}
// after
roles := []core.RoleInput{
    {Name: "admin", UserIDs: []string{"alice"}},
    {Name: "dev", UserIDs: []string{"*"}},
}
Defensive patterns

Strategy: validation

Validate before calling

wildcards := 0
for _, r := range roles {
    for _, u := range r.UserIDs {
        if u == "*" { wildcards++ }
    }
}
if wildcards > 1 {
    return errors.New("only one role may use wildcard user_ids")
}
core.ValidateRoleInputs(defaultRole, roles)

Prevention

When it happens

Trigger: Calling ValidateRoleInputs where two or more RoleInput entries include the literal "*" in their UserIDs slice.

Common situations: A config that defines a catch-all 'everyone' role plus a second role that also used "*" as a shortcut for 'any user with this role'; templated configs where the wildcard was duplicated across role blocks.

Related errors


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