nats-io/nats-server · error

eventing shut down

Error message

eventing shut down

What it means

Error returned by fetch/account-lookup when the server's internal eventing (s.sys or its replies map) is already shut down. A lookup request for an account cannot be sent or answered, so the call returns _EMPTY_ account JWT plus this error.

Source

Thrown at server/accounts.go:4732

	return res, nil
}

// Caching resolver using nats for lookups and making use of a directory for storage
type CacheDirAccResolver struct {
	DirAccResolver
	ttl time.Duration
}

func (s *Server) fetch(res AccountResolver, name string, timeout time.Duration) (string, error) {
	if s == nil {
		return _EMPTY_, ErrNoAccountResolver
	}
	respC := make(chan []byte, 1)
	accountLookupRequest := fmt.Sprintf(accLookupReqSubj, name)
	s.mu.Lock()
	if s.sys == nil || s.sys.replies == nil {
		s.mu.Unlock()
		return _EMPTY_, fmt.Errorf("eventing shut down")
	}
	// Resolver will wait for detected active servers to reply
	// before serving an error in case there weren't any found.
	expectedServers := len(s.sys.servers)
	replySubj := s.newRespInbox()
	replies := s.sys.replies

	// Store our handler.
	replies[replySubj] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) {
		var clone []byte
		isEmpty := len(msg) == 0
		if !isEmpty {
			clone = make([]byte, len(msg))
			copy(clone, msg)
		}
		s.mu.Lock()
		defer s.mu.Unlock()
		expectedServers--

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Retry the account lookup after the server is (re)started and eventing is healthy.
  2. Treat this as a shutdown signal: stop issuing lookups and drain connections.
  3. Avoid shutting down the server while account fetches are pending; drain first.
  4. Check for premature shutdown caused by fatal errors elsewhere in startup.

Example fix

// caller pattern
jwt, err := s.fetchAccount(name)
if err != nil {
    if strings.Contains(err.Error(), "eventing shut down") {
        return // server shutting down; do not retry now
    }
    // handle other lookup errors
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check eventing before lookup
s.mu.Lock()
up := s.sys != nil && s.sys.replies != nil
s.mu.Unlock()
if !up {
    return _EMPTY_, fmt.Errorf("eventing shut down")
}

Type guard

func isEventingShutdownErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "eventing shut down")
}

Try / catch

jwt, err := s.fetchAccount(name)
if isEventingShutdownErr(err) {
    // server is shutting down; abort lookup without retry
    return _EMPTY_, err
}

Prevention

When it happens

Trigger: Calling fetchAccount/lookupAccount (e.g. during an account fetch on connect or via resolver lookup) after the server began shutdown and the sys internal client/replies were torn down.

Common situations: Server shutdown races: client connections or account fetches still in flight while s.sys is being closed; tests stopping the server while lookups are pending.

Related errors


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