vitessio/vitess · error

rule %d: clusters list cannot include wildcard and other clu

Error message

rule %d: clusters list cannot include wildcard and other clusters, have %v

What it means

As the third wildcard-consistency check in RBAC config reification, clusters per rule are validated: "*" (all clusters) cannot appear alongside specific cluster names. Mixing them makes rule matching ambiguous, so Reify records a validation error naming the rule index and offending cluster list. The config must be corrected before vtadmin will start.

Source

Thrown at go/vt/vtadmin/rbac/config.go:107

	for i, rule := range c.Rules {
		resourceRules := byResource[rule.Resource]

		actions := sets.New[string](rule.Actions...)
		if actions.Has("*") && actions.Len() > 1 {
			// error to have wildcard and something else
			rec.RecordError(fmt.Errorf("rule %d: actions list cannot include wildcard and other actions, have %v", i, sets.List(actions)))
		}

		subjects := sets.New[string](rule.Subjects...)
		if subjects.Has("*") && subjects.Len() > 1 {
			// error to have wildcard and something else
			rec.RecordError(fmt.Errorf("rule %d: subjects list cannot include wildcard and other subjects, have %v", i, sets.List(subjects)))
		}

		clusters := sets.New[string](rule.Clusters...)
		if clusters.Has("*") && clusters.Len() > 1 {
			// error to have wildcard and something else
			rec.RecordError(fmt.Errorf("rule %d: clusters list cannot include wildcard and other clusters, have %v", i, sets.List(clusters)))
		}

		resourceRules = append(resourceRules, &Rule{
			actions:  actions,
			subjects: subjects,
			clusters: clusters,
		})
		byResource[rule.Resource] = resourceRules
	}

	if rec.HasErrors() {
		return rec.Error()
	}

	log.Info(fmt.Sprintf("[rbac]: loaded authorizer with %d rules", len(c.Rules)))

	c.cfg = byResource
	c.authorizer = &Authorizer{

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Keep "*" alone if the rule should apply to all clusters.
  2. Otherwise remove "*" and list only the target cluster names.
  3. Split into two rules if different resources need different cluster scopes.

Example fix

// before
{"resource": "backups", "actions": ["*"], "clusters": ["*", "prod"]}
// after
{"resource": "backups", "actions": ["*"], "clusters": ["prod"]}
Defensive patterns

Strategy: validation

Validate before calling

for i, rule := range cfg.Rules {
	if slices.Contains(rule.Clusters, "*") && len(rule.Clusters) > 1 {
		return fmt.Errorf("rule %d: clusters must be * alone or explicit list", i)
	}
}

Type guard

func clustersValid(clusters []string) bool {
	return !(slices.Contains(clusters, "*") && len(clusters) > 1)
}

Try / catch

rules, err := cfg.Reify()
if err != nil {
	log.Fatalf("fix RBAC clusters config: %v", err)
}

Prevention

When it happens

Trigger: RBAC config rule with `clusters: ["*", "local_cluster"]`, loaded through config.Reify during vtadmin startup or RBAC tests.

Common situations: Multi-cluster setups where an operator appended a specific cluster to an existing catch-all rule; config templating that merges wildcard defaults with environment-specific clusters; migrating from single-cluster to multi-cluster configs.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/0501b9d4ef7cec7e. Report an issue: GitHub.