nats-io/nats-server · warning

monitor goroutine not running

Error message

monitor goroutine not running

What it means

Returned by jetStream.isStreamHealthy when the stream's monitor goroutine (which watches the raft group and drives the replicated stream) is not running. The stream object exists and its node matches the assignment, but the background goroutine that keeps it in sync has not been started or has stopped, so the stream cannot be considered healthy.

Source

Thrown at server/jetstream_cluster.go:1063

	case node == nil:
		return errors.New("group node missing")

	case msetNode == nil:
		// Can happen when the stream's node is not yet initialized.
		return errors.New("stream node missing")

	case node != msetNode:
		s.Warnf("Detected stream cluster node skew '%s > %s'", acc.GetName(), streamName)
		return errors.New("cluster node skew detected")

	case nrgWerr != nil:
		return fmt.Errorf("node write error: %v", nrgWerr)

	case streamWerr != nil:
		return fmt.Errorf("stream write error: %v", streamWerr)

	case !mset.isMonitorRunning():
		return errors.New("monitor goroutine not running")

	case mset.isCatchingUp():
		return errors.New("stream catching up")

	case !node.Healthy():
		return errors.New("group node unhealthy")

	default:
		return nil
	}
}

// isConsumerHealthy will determine if the consumer is up to date.
// For R1 it will make sure the consunmer is present on this server.
func (js *jetStream) isConsumerHealthy(mset *stream, consumer string, ca *consumerAssignment) error {
	js.mu.RLock()
	if ca != nil && ca.unsupported != nil {
		js.mu.RUnlock()

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Retry the health check; on startup this resolves once monitors start
  2. Increase initial health-check delay / readiness probe grace period to cover JetStream init
  3. If persistent, check server logs for stream monitor errors and restart the server
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "monitor goroutine not running") {
    // startup window; retry with backoff
    time.Sleep(backoff)
    return healthcheck()
}

Prevention

When it happens

Trigger: HEALTHCHECK during the startup window before monitorAndSync runs for the stream, or after the monitor goroutine exited due to an internal error/shutdown.

Common situations: Server still starting up and initializing replicated streams; health probes in Kubernetes firing before JetStream finishes initialization; stream state after an internal fault.

Related errors


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