XTLS/Xray-core · error

duplicate balancer tag

Error message

duplicate balancer tag

What it means

While (re)building balancers, two balancingRule entries declare the same tag. Balancers are keyed by tag in a map, so duplicates would silently overwrite each other; the loader rejects instead. Note the early return leaks already-built balancers' webhooks state, but config load fails anyway.

Source

Thrown at app/router/router.go:139

}

func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if !shouldAppend {
		for _, rule := range r.rules {
			if rule.Webhook != nil {
				rule.Webhook.Close()
			}
		}
		r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
		r.rules = make([]*Rule, 0, len(config.Rule))
	}
	for _, rule := range config.BalancingRule {
		_, found := r.balancers[rule.Tag]
		if found {
			return errors.New("duplicate balancer tag")
		}
		balancer, err := rule.Build(r.ohm, r.dispatcher)
		if err != nil {
			return err
		}
		balancer.InjectContext(r.ctx)
		r.balancers[rule.Tag] = balancer
	}

	startIdx := len(r.rules)
	closeNewWebhooks := func() {
		for i := startIdx; i < len(r.rules); i++ {
			if r.rules[i].Webhook != nil {
				r.rules[i].Webhook.Close()
			}
		}
		r.rules = r.rules[:startIdx]
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Give each balancingRule a unique tag
  2. In append mode, only include new balancer tags not already loaded
  3. Lint the config for duplicate tags before submit

Example fix

// before
"balancingRule": [
  { "tag": "bal", "selector": ["a"] },
  { "tag": "bal", "selector": ["b"] }
]

// after
"balancingRule": [
  { "tag": "bal-a", "selector": ["a"] },
  { "tag": "bal-b", "selector": ["b"] }
]
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, b := range cfg.BalancingRule {
    if seen[b.Tag] { return fmt.Errorf("duplicate balancer tag %q", b.Tag) }
    seen[b.Tag] = true
}

Prevention

When it happens

Trigger: ReloadRules/AddRule config containing two balancingRule blocks with identical tag values; append-mode reload re-adding an existing balancer tag.

Common situations: Copy-pasted balancer blocks in JSON; append reloads (shouldAppend=true) that repeat tags already registered.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/08deab20821d70a3. Report an issue: GitHub.