nats-io/nats-server · error

JetStream cluster requires cluster name

Error message

JetStream cluster requires cluster name

What it means

enableJetStreamClustering returns this when JetStream clustering is being enabled but the server's cluster name is dynamic (not statically configured) and the server cannot extend another domain via leaf nodes. JetStream clustering requires a stable cluster name so raft meta groups and asset placement are consistent across restarts; a dynamically generated name would break peer identity.

Source

Thrown at server/jetstream_cluster.go:1270

	if !s.isRunning() {
		return nil
	}
	js := s.getJetStream()
	if js == nil {
		return NewJSNotEnabledForAccountError()
	}
	// Already set.
	if js.cluster != nil {
		return nil
	}

	s.Noticef("Starting JetStream cluster")
	// We need to determine if we have a stable cluster name and expected number of servers.
	s.Debugf("JetStream cluster checking for stable cluster name and peers")

	hasLeafNodeSystemShare := s.canExtendOtherDomain()
	if s.isClusterNameDynamic() && !hasLeafNodeSystemShare {
		return errors.New("JetStream cluster requires cluster name")
	}
	if s.configuredRoutes() == 0 && !hasLeafNodeSystemShare {
		return errors.New("JetStream cluster requires configured routes or solicited leafnode for the system account")
	}

	return js.setupMetaGroup()
}

// isClustered returns if we are clustered.
// Lock should not be held.
func (js *jetStream) isClustered() bool {
	// This is only ever set, no need for lock here.
	return js.cluster != nil
}

// isClusteredNoLock returns if we are clustered, but unlike isClustered() does
// not use the jetstream's lock, instead, uses an atomic operation.
// There are situations where some code wants to know if we are clustered but

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Set a stable `cluster { name: "<name>" }` block in the server config.
  2. If you intended leafnode extension, configure a solicited leafnode connection sharing the system account so hasLeafNodeSystemShare is true.
  3. Re-check the rendered config (nats-server --config ... --signal reload or start logs) to ensure the cluster name is present at runtime.
  4. Restart the server after fixing the config; clustering setup runs when JetStream clustering is enabled.

Example fix

// before
jetstream {
  store_dir: "/data/js"
}
// after
jetstream {
  store_dir: "/data/js"
}
cluster {
  name: "nats-cluster-a"
  listen: "0.0.0.0:6222"
  routes: [
    "nats://nats-1:6222",
    "nats://nats-2:6222"
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate config before startup: cluster name must be set for JS clustering
if cfg.Cluster == nil || cfg.Cluster.Name == "" {
    return errors.New("jetstream clustering requires cluster.name")
}

Try / catch

// Go: fail fast at config load time
if err := server.Start(); err != nil && strings.Contains(err.Error(), "requires cluster name") {
    return fmt.Errorf("config error: set cluster.name in server config: %w", err)
}

Prevention

When it happens

Trigger: Config has `jetstream { ... }` plus clustering enabled (store_dir etc. with js clustering via leafnode/system share absent) while `cluster { name }` is unset, causing isClusterNameDynamic() to be true; s.canExtendOtherDomain() is false because no solicited leafnode connection shares the system account.

Common situations: Operator enables JetStream clustering but forgets to set cluster.name in the config; config templating drops the cluster block; leafnode-based extension expected but the leaf connection is not configured with the system account.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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