nats-io/nats-server · error

leaf nodes and gateways (both being defined) require a syste

Error message

leaf nodes and gateways (both being defined) require a system account to also be configured

What it means

When both leaf nodes and a gateway are configured, the server requires a system account so that cluster/supercluster control messages have an account to run under. validateLeafNode throws this during Options validation when Options defines leaf node connections and a gateway (name or port) but Options.SystemAccount is empty. Without it, routing of system-level interest between leaf nodes and gateways cannot work correctly.

Source

Thrown at server/leafnode.go:349

	// If MinVersion is defined, check that it is valid.
	if mv := o.LeafNode.MinVersion; mv != _EMPTY_ {
		if err := checkLeafMinVersionConfig(mv); err != nil {
			return err
		}
	}

	// The checks below will be done only when detecting that we are configured
	// with gateways. So if an option validation needs to be done regardless,
	// it MUST be done before this point!

	if o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 {
		return nil
	}
	// If we are here we have both leaf nodes and gateways defined, make sure there
	// is a system account defined.
	if o.SystemAccount == _EMPTY_ {
		return fmt.Errorf("leaf nodes and gateways (both being defined) require a system account to also be configured")
	}
	if err := validatePinnedCerts(o.LeafNode.TLSPinnedCerts); err != nil {
		return fmt.Errorf("leafnode: %v", err)
	}
	return nil
}

func checkLeafMinVersionConfig(mv string) error {
	if ok, err := versionAtLeastCheckError(mv, 2, 8, 0); !ok || err != nil {
		if err != nil {
			return fmt.Errorf("invalid leafnode's minimum version: %v", err)
		} else {
			return fmt.Errorf("the minimum version should be at least 2.8.0")
		}
	}
	return nil
}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Add a system account to the config, e.g. accounts { SYS { ... } } and system_account = "SYS-internal-nkey"
  2. Generate an account NKEY with nsc and set it as system_account in Options
  3. If gateways are not actually needed, remove the gateway name/port configuration

Example fix

// before
leafnodes { ... }
gateway { name: "A", port: 7222 }
// after
accounts { SYS { users: [ { nkey: "AB..." } ] } }
system_account: "AB..."
leafnodes { ... }
gateway { name: "A", port: 7222 }
Defensive patterns

Strategy: validation

Validate before calling

if (opts.LeafNode != nil && hasLeafRemotes(opts)) &&
   (opts.Gateway.Name != "" || opts.Gateway.Port != 0) &&
   opts.SystemAccount == "" {
  return errors.New("leafnodes + gateway require a system account")
}

Prevention

When it happens

Trigger: Calling server.NewServer(opts) / opts.Validate() (via validateOptions -> validateLeafNode) where o.LeafNode is configured AND (o.Gateway.Name != "" or o.Gateway.Port != 0) AND o.SystemAccount == "".

Common situations: Operators add a gateway block to an existing config that only had leaf nodes (or vice versa) and forget the accounts.system_account setting; templates copied from simple leaf-node examples then extended with clustering.

Related errors


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