nats-io/nats-server · error

duplicate user detected in leafnode authorization

Error message

duplicate user %q detected in leafnode authorization

What it means

Leaf node user names must be unique; validateLeafNodeAuthOptions builds a set of usernames from the Users array and throws this error on the first duplicate. It prevents ambiguous authorization matching for leaf node connections.

Solutions

  1. Remove or rename the duplicated username in the leafnode users array
  2. Audit generated/merged configs for repeated `user:` entries before deployment
  3. Run `nats-server -t` to catch duplicates before restart

Example fix

// before
users = [ { user: "leaf", pass: "p1" }, { user: "leaf", pass: "p2" } ]
// after
users = [ { user: "leaf-a", pass: "p1" }, { user: "leaf-b", pass: "p2" } ]
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, u := range cfg.LeafNodes.Users {
  if seen[u.Username] {
    return fmt.Errorf("duplicate leafnode user %q", u.Username)
  }
  seen[u.Username] = true
}

Prevention

When it happens

Trigger: Options where two or more entries in o.LeafNode.Users share the same Username, detected while iterating the users map in validateLeafNodeAuthOptions (called from validateLeafNode and parseLeafNodes).

Common situations: Merging users arrays from multiple remote blocks in generated configs; copy-paste duplicating a user entry; tooling that appends users without deduplication.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/9c050cb1f90b113a. Report an issue: GitHub.

Appendix: source

Thrown at server/leafnode.go:384

}

// Used to validate user names in LeafNode configuration.
// - rejects mix of single and multiple users.
// - rejects duplicate user names.
func validateLeafNodeAuthOptions(o *Options) error {
	if len(o.LeafNode.Users) == 0 {
		return nil
	}
	if o.LeafNode.Username != _EMPTY_ {
		return fmt.Errorf("can not have a single user/pass and a users array")
	}
	if o.LeafNode.Nkey != _EMPTY_ {
		return fmt.Errorf("can not have a single nkey and a users array")
	}
	users := map[string]struct{}{}
	for _, u := range o.LeafNode.Users {
		if _, exists := users[u.Username]; exists {
			return fmt.Errorf("duplicate user %q detected in leafnode authorization", u.Username)
		}
		users[u.Username] = struct{}{}
	}
	return nil
}

func validateLeafNodeProxyOptions(remote *RemoteLeafOpts) ([]string, error) {
	var warnings []string

	if remote.Proxy.URL == _EMPTY_ {
		return warnings, nil
	}

	proxyURL, err := url.Parse(remote.Proxy.URL)
	if err != nil {
		return warnings, fmt.Errorf("invalid proxy URL: %v", err)
	}

View on GitHub (pinned to 3a66a489d2)