{"record":{"id":"64c110845bb3c37a","repo":"nats-io/nats-server","slug":"eventing-shut-down","errorCode":null,"errorMessage":"eventing shut down","messagePattern":"eventing shut down","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/accounts.go","lineNumber":4732,"sourceCode":"\treturn res, nil\n}\n\n// Caching resolver using nats for lookups and making use of a directory for storage\ntype CacheDirAccResolver struct {\n\tDirAccResolver\n\tttl time.Duration\n}\n\nfunc (s *Server) fetch(res AccountResolver, name string, timeout time.Duration) (string, error) {\n\tif s == nil {\n\t\treturn _EMPTY_, ErrNoAccountResolver\n\t}\n\trespC := make(chan []byte, 1)\n\taccountLookupRequest := fmt.Sprintf(accLookupReqSubj, name)\n\ts.mu.Lock()\n\tif s.sys == nil || s.sys.replies == nil {\n\t\ts.mu.Unlock()\n\t\treturn _EMPTY_, fmt.Errorf(\"eventing shut down\")\n\t}\n\t// Resolver will wait for detected active servers to reply\n\t// before serving an error in case there weren't any found.\n\texpectedServers := len(s.sys.servers)\n\treplySubj := s.newRespInbox()\n\treplies := s.sys.replies\n\n\t// Store our handler.\n\treplies[replySubj] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) {\n\t\tvar clone []byte\n\t\tisEmpty := len(msg) == 0\n\t\tif !isEmpty {\n\t\t\tclone = make([]byte, len(msg))\n\t\t\tcopy(clone, msg)\n\t\t}\n\t\ts.mu.Lock()\n\t\tdefer s.mu.Unlock()\n\t\texpectedServers--","sourceCodeStart":4714,"sourceCodeEnd":4750,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/accounts.go#L4714-L4750","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry the account lookup after the server is (re)started and eventing is healthy.","Treat this as a shutdown signal: stop issuing lookups and drain connections.","Avoid shutting down the server while account fetches are pending; drain first.","Check for premature shutdown caused by fatal errors elsewhere in startup."],"exampleFix":"// caller pattern\njwt, err := s.fetchAccount(name)\nif err != nil {\n    if strings.Contains(err.Error(), \"eventing shut down\") {\n        return // server shutting down; do not retry now\n    }\n    // handle other lookup errors\n}","handlingStrategy":"try-catch","validationCode":"// check eventing before lookup\ns.mu.Lock()\nup := s.sys != nil && s.sys.replies != nil\ns.mu.Unlock()\nif !up {\n    return _EMPTY_, fmt.Errorf(\"eventing shut down\")\n}","typeGuard":"func isEventingShutdownErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"eventing shut down\")\n}","tryCatchPattern":"jwt, err := s.fetchAccount(name)\nif isEventingShutdownErr(err) {\n    // server is shutting down; abort lookup without retry\n    return _EMPTY_, err\n}","preventionTips":["Drain clients and stop account fetches before server shutdown.","Treat this error as terminal during shutdown, not retryable.","Watch for shutdown races in tests stopping servers with pending lookups.","Monitor logs for unexpected eventing teardown during normal operation."],"tags":["nats-server","shutdown-race","account-lookup","eventing"],"backgroundTag":"server-shutting-down","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}