micro/go-micro · critical

error connecting to nats cluster %v: %w

Error message

error connecting to nats cluster %v: %w

What it means

NewStream wraps any failure from connectToNatsJetStream (which dials the NATS servers and creates the JetStream context) into 'error connecting to nats cluster <ClusterID>: <cause>'. The wrapped cause carries the real reason — DNS failure, connection refused, TLS error, auth failure, or timeout.

Source

Thrown at events/natsjs/nats.go:41

// NewStream returns an initialized nats stream or an error if the connection to the nats
// server could not be established.
func NewStream(opts ...Option) (events.Stream, error) {
	// parse the options
	options := Options{
		ClientID:  uuid.New().String(),
		ClusterID: defaultClusterID,
		Logger:    logger.DefaultLogger,
	}
	for _, o := range opts {
		o(&options)
	}

	s := &stream{opts: options}

	conn, natsJetStreamCtx, err := connectToNatsJetStream(options)
	if err != nil {
		return nil, fmt.Errorf("error connecting to nats cluster %v: %w", options.ClusterID, err)
	}

	s.conn = conn
	s.natsJetStreamCtx = natsJetStreamCtx

	return s, nil
}

type stream struct {
	opts             Options
	conn             *nats.Conn // store connection for lifecycle management
	natsJetStreamCtx nats.JetStreamContext
}

func connectToNatsJetStream(options Options) (*nats.Conn, nats.JetStreamContext, error) {
	nopts := nats.GetDefaultOptions()
	if options.TLSConfig != nil {
		nopts.Secure = true

View on GitHub (pinned to 24529f1404)

Solutions

  1. Unwrap the error (%w) and fix the underlying cause — usually connection refused or auth failure at the NATS server
  2. Confirm the NATS servers' addresses via events.Address(...) and that they are reachable (nc -vz host 4222)
  3. Ensure the server's cluster name matches your ClusterID option (default is "micro")
  4. Check credentials/TLSConfig options and that JetStream is enabled on the server
  5. Add retry/backoff around NewStream for transient network issues at startup

Example fix

// before
stream, err := natsjs.NewStream() // error connecting to nats cluster micro: ...
// after
stream, err := natsjs.NewStream(
    natsjs.Address("nats://nats1:4222", "nats://nats2:4222"),
    natsjs.ClusterID("my-cluster"),
)
Defensive patterns

Strategy: retry

Validate before calling

// probe reachability before constructing the stream
for _, addr := range addrs {
    conn, err := net.DialTimeout("tcp", addr, 2*time.Second)
    if err != nil { return fmt.Errorf("nats %s unreachable: %w", addr, err) }
    conn.Close()
}

Try / catch

var stream events.Stream
err := retry.Do(3, 2*time.Second, func() error {
    s, err := natsjs.NewStream(natsjs.Address(addrs...), natsjs.ClusterID(cluster))
    if err != nil {
        log.Warn("nats connect failed:", err) // %w cause is inside
        return err
    }
    stream = s
    return nil
})

Prevention

When it happens

Trigger: Calling events/natsjs.NewStream when the NATS servers for the configured ClusterID are unreachable: wrong addresses, cluster down, bad credentials/TLS, or the default cluster id 'micro' not matching your deployment.

Common situations: Local development without a NATS cluster running; connecting to a NATS cluster whose cluster name differs from the default 'micro'; firewall/network policy blocking port 4222; expired or wrong NATS credentials in the environment.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/1f48c64a365f3e2e. Report an issue: GitHub.