Repository: nats-io/nats-server
Pull request #5690 (2024-07-23 17:51:58)

Remove Go 1.20 from build, force building Go >= 1.21 in go.mod
Follow up https://github.com/nats-io/nats-server/pull/5636




Patch:
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 91905885..51a0d21d 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -16,7 +16,7 @@ builds:
   flags:
   - -trimpath
   ldflags:
-    - -w -X 'github.com/nats-io/nats-server/v2/server.gitCommit={{.ShortCommit}}' -X 'github.com/nats-io/nats-server/v2/server.serverVersion={{.Tag}}'
+    - -w -X github.com/nats-io/nats-server/v2/server.gitCommit={{.ShortCommit}}
   env:
     - GO111MODULE=on
     - CGO_ENABLED=0
diff --git a/.travis.yml b/.travis.yml
index 1c62c778..ed61ef35 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -47,7 +47,7 @@ jobs:
     - name: "Run all tests from all other packages"
       env: TEST_SUITE=non_srv_pkg_tests
     - name: "Compile with older Go release"
-      go: "1.20"
+      go: "1.21.x"
       env: TEST_SUITE=build_only
 
 script: ./scripts/runTestsOnTravis.sh $TEST_SUITE
@@ -55,7 +55,7 @@ script: ./scripts/runTestsOnTravis.sh $TEST_SUITE
 deploy:
   provider: script
   cleanup: true
-  script: curl -o /tmp/goreleaser.tar.gz -sLf https://github.com/goreleaser/goreleaser/releases/download/v1.26.2/goreleaser_Linux_x86_64.tar.gz && tar -xvf /tmp/goreleaser.tar.gz -C /tmp/ && /tmp/goreleaser
+  script: curl -o goreleaser.tar.gz -sLf https://github.com/goreleaser/goreleaser/releases/download/v1.26.2/goreleaser_Linux_x86_64.tar.gz && tar -xvf goreleaser.tar.gz && ./goreleaser
   on:
     tags: true
     condition: ($TRAVIS_GO_VERSION =~ 1.22) && ($TEST_SUITE = "compile")
diff --git a/go.mod b/go.mod
index 4ff5b942..177b95c4 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/nats-io/nats-server/v2
 
-go 1.21
+go 1.21.0
 
 require (
 	github.com/google/go-tpm v0.9.1
diff --git a/server/accounts.go b/server/accounts.go
index 05a78154..aca96b5d 100644
--- a/server/accounts.go
+++ b/server/accounts.go
@@ -660,7 +660,7 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error {
 		if tw[d.Cluster] > 100 {
 			return fmt.Errorf("total weight needs to be <= 100")
 		}
-		err := ValidateMapping(src, d.Subject)
+		err := ValidateMappingDestination(d.Subject)
 		if err != nil {
 			return err
 		}
diff --git a/server/const.go b/server/const.go
index 8b88341f..82e968f5 100644
--- a/server/const.go
+++ b/server/const.go
@@ -15,7 +15,6 @@ package server
 
 import (
 	"regexp"
-	"runtime/debug"
 	"time"
 )
 
@@ -35,27 +34,14 @@ const (
 )
 
 var (
-	// gitCommit and serverVersion injected at build.
-	gitCommit, serverVersion string
+	// gitCommit injected at build
+	gitCommit string
 	// trustedKeys is a whitespace separated array of trusted operator's public nkeys.
 	trustedKeys string
 	// SemVer regexp to validate the VERSION.
 	semVerRe = regexp.MustCompile(`^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
 )
 
-func init() {
-	// Use build info if present, it would be if building using 'go build .'
-	// or when using a release.
-	if info, ok := debug.ReadBuildInfo(); ok {
-		for _, setting := range info.Settings {
-			switch setting.Key {
-			case "vcs.revision":
-				gitCommit = setting.Value[:7]
-			}
-		}
-	}
-}
-
 const (
 	// VERSION is the current version for the server.
 	VERSION = "2.11.0-dev"
diff --git a/server/consumer.go b/server/consumer.go
index 308fa0e6..85a5fe90 100644
--- a/server/consumer.go
+++ b/server/consumer.go
@@ -5610,13 +5610,10 @@ func (o *consumer) checkStateForInterestStream() error {
 	o.mu.RUnlock()
 
 	// If we have pending, we will need to walk through to delivered in case we missed any of those acks as well.
-	if state != nil && len(state.Pending) > 0 && state.AckFloor.Stream > 0 {
+	if state != nil && len(state.Pending) > 0 {
 		for seq := state.AckFloor.Stream + 1; seq <= state.Delivered.Stream; seq++ {
 			if _, ok := state.Pending[seq]; !ok {
-				// Want to call needAck since it is filter aware.
-				if o.needAck(seq, _EMPTY_) {
-					mset.ackMsg(o, seq)
-				}
+				mset.ackMsg(o, seq)
 			}
 		}
 	}
diff --git a/server/errors.go b/server/errors.go
index fc8d703c..8efa7ac0 100644
--- a/server/errors.go
+++ b/server/errors.go
@@ -153,9 +153,6 @@ var (
 	// Gateway's name.
 	ErrWrongGateway = errors.New("wrong gateway")
 
-	// ErrGatewayNameHasSpaces signals that the gateway name contains spaces, which is not allowed.
-	ErrGatewayNameHasSpaces = errors.New("gateway name cannot contain spaces")
-
 	// ErrNoSysAccount is returned when an attempt to publish or subscribe is made
 	// when there is no internal system account defined.
 	ErrNoSysAccount = errors.New("system account not setup")
@@ -166,9 +163,6 @@ var (
 	// ErrServerNotRunning is used to signal an error that a server is not running.
 	ErrServerNotRunning = errors.New("server is not running")
 
-	// ErrServerNameHasSpaces signals that the server name contains spaces, which is not allowed.
-	ErrServerNameHasSpaces = errors.New("server name cannot contain spaces")
-
 	// ErrBadMsgHeader signals the parser detected a bad message header
 	ErrBadMsgHeader = errors.New("bad message header detected")
 
@@ -186,9 +180,6 @@ var (
 	// ErrClusterNameRemoteConflict signals that a remote server has a different cluster name.
 	ErrClusterNameRemoteConflict = errors.New("cluster name from remote server conflicts")
 
-	// ErrClusterNameHasSpaces signals that the cluster name contains spaces, which is not allowed.
-	ErrClusterNameHasSpaces = errors.New("cluster name cannot contain spaces")
-
 	// ErrMalformedSubject is returned when a subscription is made with a subject that does not conform to subject rules.
 	ErrMalformedSubject = errors.New("malformed subject")
 
@@ -212,7 +203,7 @@ var (
 	ErrInvalidMappingDestination = errors.New("invalid mapping destination")
 
 	// ErrInvalidMappingDestinationSubject is used to error on a bad transform destination mapping
-	ErrInvalidMappingDestinationSubject = fmt.Errorf("%w: invalid transform", ErrInvalidMappingDestination)
+	ErrInvalidMappingDestinationSubject = fmt.Errorf("%w: invalid subject", ErrInvalidMappingDestination)
 
 	// ErrMappingDestinationNotUsingAllWildcards is used to error on a transform destination not using all of the token wildcards
 	ErrMappingDestinationNotUsingAllWildcards = fmt.Errorf("%w: not using all of the token wildcard(s)", ErrInvalidMappingDestination)
diff --git a/server/errors.json b/server/errors.json
index 91c70bdf..79602466 100644
--- a/server/errors.json
+++ b/server/errors.json
@@ -833,7 +833,7 @@
     "constant": "JSConsumerPullRequiresAckErr",
     "code": 400,
     "error_code": 10084,
-    "description": "consumer in pull mode requires ack policy on workqueue stream",
+    "description": "consumer in pull mode requires ack policy",
     "comment": "",
     "help": "",
     "url": "",
@@ -1433,7 +1433,7 @@
     "constant": "JSSourceInvalidSubjectFilter",
     "code": 400,
     "error_code": 10145,
-    "description": "source transform source: {err}",
+    "description": "source subject filter is invalid",
     "comment": "",
     "help": "",
     "url": "",
@@ -1443,7 +1443,7 @@
     "constant": "JSSourceInvalidTransformDestination",
     "code": 400,
     "error_code": 10146,
-    "description": "source transform: {err}",
+    "description": "source transform destination is invalid",
     "comment": "",
     "help": "",
     "url": "",
@@ -1493,7 +1493,7 @@
     "constant": "JSMirrorInvalidSubjectFilter",
     "code": 400,
     "error_code": 10151,
-    "description": "mirror transform source: {err}",
+    "description": "mirror subject filter is invalid",
     "comment": "",
     "help": "",
     "url": "",
@@ -1518,35 +1518,5 @@
     "help": "",
     "url": "",
     "deprecates": ""
-  },
-  {
-    "constant": "JSMirrorInvalidTransformDestination",
-    "code": 400,
-    "error_code": 10154,
-    "description": "mirror transform: {err}",
-    "comment": "",
-    "help": "",
-    "url": "",
-    "deprecates": ""
-  },
-  {
-    "constant": "JSStreamTransformInvalidSource",
-    "code": 400,
-    "error_code": 10155,
-    "description": "stream transform source: {err}",
-    "comment": "",
-    "help": "",
-    "url": "",
-    "deprecates": ""
-  },
-  {
-    "constant": "JSStreamTransformInvalidDestination",
-    "code": 400,
-    "error_code": 10156,
-    "description": "stream transform: {err}",
-    "comment": "",
-    "help": "",
-    "url": "",
-    "deprecates": ""
   }
 ]
diff --git a/server/events.go b/server/events.go
index 83f9a850..ff940571 100644
--- a/server/events.go
+++ b/server/events.go
@@ -1066,56 +1066,44 @@ func (s *Server) Node() string {
 // Tradeoff is subscription and interest graph events vs connect and
 // disconnect events, etc.
 func (s *Server) initEventTracking() {
-	// Capture sys in case we are shutdown while setting up.
-	s.mu.RLock()
-	sys := s.sys
-	s.mu.RUnlock()
-
-	if sys == nil || sys.client == nil || sys.account == nil {
+	if !s.EventsEnabled() {
 		return
 	}
 	// Create a system hash which we use for other servers to target us specifically.
-	sys.shash = getHash(s.info.Name)
+	s.sys.shash = getHash(s.info.Name)
 
 	// This will be for all inbox responses.
-	subject := fmt.Sprintf(inboxRespSubj, sys.shash, "*")
+	subject := fmt.Sprintf(inboxRespSubj, s.sys.shash, "*")
 	if _, err := s.sysSubscribe(subject, s.inboxReply); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
-	sys.inboxPre = subject
+	s.sys.inboxPre = subject
 	// This is for remote updates for connection accounting.
 	subject = fmt.Sprintf(accConnsEventSubjOld, "*")
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteConnsUpdate)); err != nil {
 		s.Errorf("Error setting up internal tracking for %s: %v", subject, err)
-		return
 	}
 	// This will be for responses for account info that we send out.
 	subject = fmt.Sprintf(connsRespSubj, s.info.ID)
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteConnsUpdate)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	// Listen for broad requests to respond with number of subscriptions for a given subject.
 	if _, err := s.sysSubscribe(accNumSubsReqSubj, s.noInlineCallback(s.nsubsRequest)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	// Listen for statsz from others.
 	subject = fmt.Sprintf(serverStatsSubj, "*")
 	if sub, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerUpdate)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	} else {
 		// Keep track of this one.
-		sys.remoteStatsSub = sub
+		s.sys.remoteStatsSub = sub
 	}
-
 	// Listen for all server shutdowns.
 	subject = fmt.Sprintf(shutdownEventSubj, "*")
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerShutdown)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	// Listen for servers entering lame-duck mode.
 	// NOTE: This currently is handled in the same way as a server shutdown, but has
@@ -1123,7 +1111,6 @@ func (s *Server) initEventTracking() {
 	subject = fmt.Sprintf(lameDuckEventSubj, "*")
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerShutdown)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	// Listen for account claims updates.
 	subscribeToUpdate := true
@@ -1134,7 +1121,6 @@ func (s *Server) initEventTracking() {
 		for _, sub := range []string{accUpdateEventSubjOld, accUpdateEventSubjNew} {
 			if _, err := s.sysSubscribe(fmt.Sprintf(sub, "*"), s.noInlineCallback(s.accountClaimUpdate)); err != nil {
 				s.Errorf("Error setting up internal tracking: %v", err)
-				return
 			}
 		}
 	}
@@ -1142,7 +1128,6 @@ func (s *Server) initEventTracking() {
 	// This subscription is kept for backwards compatibility. Got replaced by ...PING.STATZ from below
 	if _, err := s.sysSubscribe(serverStatsPingReqSubj, s.noInlineCallback(s.statszReq)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	monSrvc := map[string]sysMsgHandler{
 		"IDZ":    s.idzReq,
@@ -1196,12 +1181,10 @@ func (s *Server) initEventTracking() {
 		subject = fmt.Sprintf(serverDirectReqSubj, s.info.ID, name)
 		if _, err := s.sysSubscribe(subject, s.noInlineCallback(req)); err != nil {
 			s.Errorf("Error setting up internal tracking: %v", err)
-			return
 		}
 		subject = fmt.Sprintf(serverPingReqSubj, name)
 		if _, err := s.sysSubscribe(subject, s.noInlineCallback(req)); err != nil {
 			s.Errorf("Error setting up internal tracking: %v", err)
-			return
 		}
 	}
 	extractAccount := func(subject string) (string, error) {
@@ -1294,7 +1277,6 @@ func (s *Server) initEventTracking() {
 	for name, req := range monAccSrvc {
 		if _, err := s.sysSubscribe(fmt.Sprintf(accDirectReqSubj, "*", name), s.noInlineCallback(req)); err != nil {
 			s.Errorf("Error setting up internal tracking: %v", err)
-			return
 		}
 	}
 
@@ -1303,7 +1285,6 @@ func (s *Server) initEventTracking() {
 	// is only one that will answer. This breaks tests since we still forward on remote server connect.
 	if _, err := s.sysSubscribe(fmt.Sprintf(userDirectReqSubj, "*"), s.userInfoReq); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 
 	// For now only the STATZ subject has an account specific ping equivalent.
@@ -1321,7 +1302,6 @@ func (s *Server) initEventTracking() {
 			})
 		})); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 
 	// Listen for updates when leaf nodes connect for a given account. This will
@@ -1329,38 +1309,32 @@ func (s *Server) initEventTracking() {
 	subject = fmt.Sprintf(leafNodeConnectEventSubj, "*")
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.leafNodeConnected)); err != nil {
 		s.Errorf("Error setting up internal tracking: %v", err)
-		return
 	}
 	// For tracking remote latency measurements.
-	subject = fmt.Sprintf(remoteLatencyEventSubj, sys.shash)
+	subject = fmt.Sprintf(remoteLatencyEventSubj, s.sys.shash)
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteLatencyUpdate)); err != nil {
 		s.Errorf("Error setting up internal latency tracking: %v", err)
-		return
 	}
 	// This is for simple debugging of number of subscribers that exist in the system.
 	if _, err := s.sysSubscribeInternal(accSubsSubj, s.noInlineCallback(s.debugSubscribers)); err != nil {
 		s.Errorf("Error setting up internal debug service for subscribers: %v", err)
-		return
 	}
 
 	// Listen for requests to reload the server configuration.
 	subject = fmt.Sprintf(serverReloadReqSubj, s.info.ID)
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.reloadConfig)); err != nil {
 		s.Errorf("Error setting up server reload handler: %v", err)
-		return
 	}
 
 	// Client connection kick
 	subject = fmt.Sprintf(clientKickReqSubj, s.info.ID)
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.kickClient)); err != nil {
 		s.Errorf("Error setting up client kick service: %v", err)
-		return
 	}
 	// Client connection LDM
 	subject = fmt.Sprintf(clientLDMReqSubj, s.info.ID)
 	if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.ldmClient)); err != nil {
 		s.Errorf("Error setting up client LDM service: %v", err)
-		return
 	}
 }
 
diff --git a/server/filestore.go b/server/filestore.go
index b034ac77..6e10ede8 100644
--- a/server/filestore.go
+++ b/server/filestore.go
@@ -2975,10 +2975,6 @@ func (fs *fileStore) NumPending(sseq uint64, filter string, lastPerSubject bool)
 		return 0, validThrough
 	}
 
-	// If sseq is less then our first set to first.
-	if sseq < fs.state.FirstSeq {
-		sseq = fs.state.FirstSeq
-	}
 	// Track starting for both block for the sseq and staring block that matches any subject.
 	var seqStart int
 	// See if we need to figure out starting block per sseq.
diff --git a/server/gateway.go b/server/gateway.go
index be175467..d8d434a2 100644
--- a/server/gateway.go
+++ b/server/gateway.go
@@ -18,14 +18,12 @@ import (
 	"crypto/sha256"
 	"crypto/tls"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"math/rand"
 	"net"
 	"net/url"
 	"sort"
 	"strconv"
-	"strings"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -301,20 +299,17 @@ func (r *RemoteGatewayOpts) clone() *RemoteGatewayOpts {
 
 // Ensure that gateway is properly configured.
 func validateGatewayOptions(o *Options) error {
-	if o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 {
+	if o.Gateway.Name == "" && o.Gateway.Port == 0 {
 		return nil
 	}
-	if o.Gateway.Name == _EMPTY_ {
-		return errors.New("gateway has no name")
-	}
-	if strings.Contains(o.Gateway.Name, " ") {
-		return ErrGatewayNameHasSpaces
+	if o.Gateway.Name == "" {
+		return fmt.Errorf("gateway has no name")
 	}
 	if o.Gateway.Port == 0 {
 		return fmt.Errorf("gateway %q has no port specified (select -1 for random port)", o.Gateway.Name)
 	}
 	for i, g := range o.Gateway.Gateways {
-		if g.Name == _EMPTY_ {
+		if g.Name == "" {
 			return fmt.Errorf("gateway in the list %d has no name", i)
 		}
 		if len(g.URLs) == 0 {
diff --git a/server/jetstream_cluster.go b/server/jetstream_cluster.go
index fef9958a..90e9b132 100644
--- a/server/jetstream_cluster.go
+++ b/server/jetstream_cluster.go
@@ -5200,7 +5200,9 @@ func (js *jetStream) processConsumerLeaderChange(o *consumer, isLeader bool) err
 	} else {
 		resp.ConsumerInfo = o.initialInfo()
 		s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp))
-		o.sendCreateAdvisory()
+		if node := o.raftNode(); node != nil {
+			o.sendCreateAdvisory()
+		}
 	}
 
 	// Only send a pause advisory on consumer create if we're
diff --git a/server/jetstream_errors_generated.go b/server/jetstream_errors_generated.go
index 277675fa..1543eeeb 100644
--- a/server/jetstream_errors_generated.go
+++ b/server/jetstream_errors_generated.go
@@ -176,7 +176,7 @@ const (
 	// JSConsumerPullNotDurableErr consumer in pull mode requires a durable name
 	JSConsumerPullNotDurableErr ErrorIdentifier = 10085
 
-	// JSConsumerPullRequiresAckErr consumer in pull mode requires ack policy on workqueue stream
+	// JSConsumerPullRequiresAckErr consumer in pull mode requires ack policy
 	JSConsumerPullRequiresAckErr ErrorIdentifier = 10084
 
 	// JSConsumerPullWithRateLimitErr consumer in pull mode can not have rate limit set
@@ -236,12 +236,9 @@ const (
 	// JSMirrorInvalidStreamName mirrored stream name is invalid
 	JSMirrorInvalidStreamName ErrorIdentifier = 10142
 
-	// JSMirrorInvalidSubjectFilter mirror transform source: {err}
+	// JSMirrorInvalidSubjectFilter mirror subject filter is invalid
 	JSMirrorInvalidSubjectFilter ErrorIdentifier = 10151
 
-	// JSMirrorInvalidTransformDestination mirror transform: {err}
-	JSMirrorInvalidTransformDestination ErrorIdentifier = 10154
-
 	// JSMirrorMaxMessageSizeTooBigErr stream mirror must have max message size >= source
 	JSMirrorMaxMessageSizeTooBigErr ErrorIdentifier = 10030
 
@@ -311,10 +308,10 @@ const (
 	// JSSourceInvalidStreamName sourced stream name is invalid
 	JSSourceInvalidStreamName ErrorIdentifier = 10141
 
-	// JSSourceInvalidSubjectFilter source transform source: {err}
+	// JSSourceInvalidSubjectFilter source subject filter is invalid
 	JSSourceInvalidSubjectFilter ErrorIdentifier = 10145
 
-	// JSSourceInvalidTransformDestination source transform: {err}
+	// JSSourceInvalidTransformDestination source transform destination is invalid
 	JSSourceInvalidTransformDestination ErrorIdentifier = 10146
 
 	// JSSourceMaxMessageSizeTooBigErr stream source must have max message size >= target
@@ -449,12 +446,6 @@ const (
 	// JSStreamTemplateNotFoundErr template not found
 	JSStreamTemplateNotFoundErr ErrorIdentifier = 10068
 
-	// JSStreamTransformInvalidDestination stream transform: {err}
-	JSStreamTransformInvalidDestination ErrorIdentifier = 10156
-
-	// JSStreamTransformInvalidSource stream transform source: {err}
-	JSStreamTransformInvalidSource ErrorIdentifier = 10155
-
 	// JSStreamUpdateErrF Generic stream update error string ({err})
 	JSStreamUpdateErrF ErrorIdentifier = 10069
 
@@ -530,7 +521,7 @@ var (
 		JSConsumerOnMappedErr:                      {Code: 400, ErrCode: 10092, Description: "consumer direct on a mapped consumer"},
 		JSConsumerOverlappingSubjectFilters:        {Code: 400, ErrCode: 10138, Description: "consumer subject filters cannot overlap"},
 		JSConsumerPullNotDurableErr:                {Code: 400, ErrCode: 10085, Description: "consumer in pull mode requires a durable name"},
-		JSConsumerPullRequiresAckErr:               {Code: 400, ErrCode: 10084, Description: "consumer in pull mode requires ack policy on workqueue stream"},
+		JSConsumerPullRequiresAckErr:               {Code: 400, ErrCode: 10084, Description: "consumer in pull mode requires ack policy"},
 		JSConsumerPullWithRateLimitErr:             {Code: 400, ErrCode: 10086, Description: "consumer in pull mode can not have rate limit set"},
 		JSConsumerPushMaxWaitingErr:                {Code: 400, ErrCode: 10080, Description: "consumer in push mode can not set max waiting"},
 		JSConsumerReplacementWithDifferentNameErr:  {Code: 400, ErrCode: 10106, Description: "consumer replacement durable config not the same"},
@@ -550,8 +541,7 @@ var (
 		JSMemoryResourcesExceededErr:               {Code: 500, ErrCode: 10028, Description: "insufficient memory resources available"},
 		JSMirrorConsumerSetupFailedErrF:            {Code: 500, ErrCode: 10029, Description: "{err}"},
 		JSMirrorInvalidStreamName:                  {Code: 400, ErrCode: 10142, Description: "mirrored stream name is invalid"},
-		JSMirrorInvalidSubjectFilter:               {Code: 400, ErrCode: 10151, Description: "mirror transform source: {err}"},
-		JSMirrorInvalidTransformDestination:        {Code: 400, ErrCode: 10154, Description: "mirror transform: {err}"},
+		JSMirrorInvalidSubjectFilter:               {Code: 400, ErrCode: 10151, Description: "mirror subject filter is invalid"},
 		JSMirrorMaxMessageSizeTooBigErr:            {Code: 400, ErrCode: 10030, Description: "stream mirror must have max message size >= source"},
 		JSMirrorMultipleFiltersNotAllowed:          {Code: 400, ErrCode: 10150, Description: "mirror with multiple subject transforms cannot also have a single subject filter"},
 		JSMirrorOverlappingSubjectFilters:          {Code: 400, ErrCode: 10152, Description: "mirror subject filters can not overlap"},
@@ -575,8 +565,8 @@ var (
 		JSSourceConsumerSetupFailedErrF:            {Code: 500, ErrCode: 10045, Description: "{err}"},
 		JSSourceDuplicateDetected:                  {Code: 400, ErrCode: 10140, Description: "duplicate source configuration detected"},
 		JSSourceInvalidStreamName:                  {Code: 400, ErrCode: 10141, Description: "sourced stream name is invalid"},
-		JSSourceInvalidSubjectFilter:               {Code: 400, ErrCode: 10145, Description: "source transform source: {err}"},
-		JSSourceInvalidTransformDestination:        {Code: 400, ErrCode: 10146, Description: "source transform: {err}"},
+		JSSourceInvalidSubjectFilter:               {Code: 400, ErrCode: 10145, Description: "source subject filter is invalid"},
+		JSSourceInvalidTransformDestination:        {Code: 400, ErrCode: 10146, Description: "source transform destination is invalid"},
 		JSSourceMaxMessageSizeTooBigErr:            {Code: 400, ErrCode: 10046, Description: "stream source must have max message size >= target"},
 		JSSourceMultipleFiltersNotAllowed:          {Code: 400, ErrCode: 10144, Description: "source with multiple subject transforms cannot also have a single subject filter"},
 		JSSourceOverlappingSubjectFilters:          {Code: 400, ErrCode: 10147, Description: "source filters can not overlap"},
@@ -621,8 +611,6 @@ var (
 		JSStreamTemplateCreateErrF:                 {Code: 500, ErrCode: 10066, Description: "{err}"},
 		JSStreamTemplateDeleteErrF:                 {Code: 500, ErrCode: 10067, Description: "{err}"},
 		JSStreamTemplateNotFoundErr:                {Code: 404, ErrCode: 10068, Description: "template not found"},
-		JSStreamTransformInvalidDestination:        {Code: 400, ErrCode: 10156, Description: "stream transform: {err}"},
-		JSStreamTransformInvalidSource:             {Code: 400, ErrCode: 10155, Description: "stream transform source: {err}"},
 		JSStreamUpdateErrF:                         {Code: 500, ErrCode: 10069, Description: "{err}"},
 		JSStreamWrongLastMsgIDErrF:                 {Code: 400, ErrCode: 10070, Description: "wrong last msg ID: {id}"},
 		JSStreamWrongLastSequenceErrF:              {Code: 400, ErrCode: 10071, Description: "wrong last sequence: {seq}"},
@@ -1283,7 +1271,7 @@ func NewJSConsumerPullNotDurableError(opts ...ErrorOption) *ApiError {
 	return ApiErrors[JSConsumerPullNotDurableErr]
 }
 
-// NewJSConsumerPullRequiresAckError creates a new JSConsumerPullRequiresAckErr error: "consumer in pull mode requires ack policy on workqueue stream"
+// NewJSConsumerPullRequiresAckError creates a new JSConsumerPullRequiresAckErr error: "consumer in pull mode requires ack policy"
 func NewJSConsumerPullRequiresAckError(opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
 	if ae, ok := eopts.err.(*ApiError); ok {
@@ -1495,36 +1483,14 @@ func NewJSMirrorInvalidStreamNameError(opts ...ErrorOption) *ApiError {
 	return ApiErrors[JSMirrorInvalidStreamName]
 }
 
-// NewJSMirrorInvalidSubjectFilterError creates a new JSMirrorInvalidSubjectFilter error: "mirror transform source: {err}"
-func NewJSMirrorInvalidSubjectFilterError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSMirrorInvalidSubjectFilter]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSMirrorInvalidTransformDestinationError creates a new JSMirrorInvalidTransformDestination error: "mirror transform: {err}"
-func NewJSMirrorInvalidTransformDestinationError(err error, opts ...ErrorOption) *ApiError {
+// NewJSMirrorInvalidSubjectFilterError creates a new JSMirrorInvalidSubjectFilter error: "mirror subject filter is invalid"
+func NewJSMirrorInvalidSubjectFilterError(opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
 	if ae, ok := eopts.err.(*ApiError); ok {
 		return ae
 	}
 
-	e := ApiErrors[JSMirrorInvalidTransformDestination]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
+	return ApiErrors[JSMirrorInvalidSubjectFilter]
 }
 
 // NewJSMirrorMaxMessageSizeTooBigError creates a new JSMirrorMaxMessageSizeTooBigErr error: "stream mirror must have max message size >= source"
@@ -1781,36 +1747,24 @@ func NewJSSourceInvalidStreamNameError(opts ...ErrorOption) *ApiError {
 	return ApiErrors[JSSourceInvalidStreamName]
 }
 
-// NewJSSourceInvalidSubjectFilterError creates a new JSSourceInvalidSubjectFilter error: "source transform source: {err}"
-func NewJSSourceInvalidSubjectFilterError(err error, opts ...ErrorOption) *ApiError {
+// NewJSSourceInvalidSubjectFilterError creates a new JSSourceInvalidSubjectFilter error: "source subject filter is invalid"
+func NewJSSourceInvalidSubjectFilterError(opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
 	if ae, ok := eopts.err.(*ApiError); ok {
 		return ae
 	}
 
-	e := ApiErrors[JSSourceInvalidSubjectFilter]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
+	return ApiErrors[JSSourceInvalidSubjectFilter]
 }
 
-// NewJSSourceInvalidTransformDestinationError creates a new JSSourceInvalidTransformDestination error: "source transform: {err}"
-func NewJSSourceInvalidTransformDestinationError(err error, opts ...ErrorOption) *ApiError {
+// NewJSSourceInvalidTransformDestinationError creates a new JSSourceInvalidTransformDestination error: "source transform destination is invalid"
+func NewJSSourceInvalidTransformDestinationError(opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
 	if ae, ok := eopts.err.(*ApiError); ok {
 		return ae
 	}
 
-	e := ApiErrors[JSSourceInvalidTransformDestination]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
+	return ApiErrors[JSSourceInvalidTransformDestination]
 }
 
 // NewJSSourceMaxMessageSizeTooBigError creates a new JSSourceMaxMessageSizeTooBigErr error: "stream source must have max message size >= target"
@@ -2361,38 +2315,6 @@ func NewJSStreamTemplateNotFoundError(opts ...ErrorOption) *ApiError {
 	return ApiErrors[JSStreamTemplateNotFoundErr]
 }
 
-// NewJSStreamTransformInvalidDestinationError creates a new JSStreamTransformInvalidDestination error: "stream transform: {err}"
-func NewJSStreamTransformInvalidDestinationError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamTransformInvalidDestination]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamTransformInvalidSourceError creates a new JSStreamTransformInvalidSource error: "stream transform source: {err}"
-func NewJSStreamTransformInvalidSourceError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamTransformInvalidSource]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
 // NewJSStreamUpdateError creates a new JSStreamUpdateErrF error: "{err}"
 func NewJSStreamUpdateError(err error, opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
diff --git a/server/leafnode.go b/server/leafnode.go
index 61ba2207..f8624406 100644
--- a/server/leafnode.go
+++ b/server/leafnode.go
@@ -1288,13 +1288,6 @@ func (c *client) processLeafnodeInfo(info *Info) {
 			c.closeConnection(WrongPort)
 			return
 		}
-		// Reject a cluster that contains spaces.
-		if info.Cluster != _EMPTY_ && strings.Contains(info.Cluster, " ") {
-			c.mu.Unlock()
-			c.sendErrAndErr(ErrClusterNameHasSpaces.Error())
-			c.closeConnection(ProtocolViolation)
-			return
-		}
 		// Capture a nonce here.
 		c.nonce = []byte(info.Nonce)
 		if info.TLSRequired && didSolicit {
@@ -1786,13 +1779,6 @@ func (c *client) processLeafNodeConnect(s *Server, arg []byte, lang string) erro
 		return err
 	}
 
-	// Reject a cluster that contains spaces.
-	if proto.Cluster != _EMPTY_ && strings.Contains(proto.Cluster, " ") {
-		c.sendErrAndErr(ErrClusterNameHasSpaces.Error())
-		c.closeConnection(ProtocolViolation)
-		return ErrClusterNameHasSpaces
-	}
-
 	// Check for cluster name collisions.
 	if cn := s.cachedClusterName(); cn != _EMPTY_ && proto.Cluster != _EMPTY_ && proto.Cluster == cn {
 		c.sendErrAndErr(ErrLeafNodeHasSameClusterName.Error())
diff --git a/server/monitor.go b/server/monitor.go
index 20fab4ff..c0c2bc08 100644
--- a/server/monitor.go
+++ b/server/monitor.go
@@ -1387,8 +1387,6 @@ func (s *Server) HandleRoot(w http.ResponseWriter, r *http.Request) {
 	var srcUrl string
 	if gitCommit == _EMPTY_ {
 		srcUrl = "https://github.com/nats-io/nats-server"
-	} else if serverVersion != _EMPTY_ {
-		srcUrl = fmt.Sprintf("https://github.com/nats-io/nats-server/tree/%s", serverVersion)
 	} else {
 		srcUrl = fmt.Sprintf("https://github.com/nats-io/nats-server/tree/%s", gitCommit)
 	}
@@ -2795,7 +2793,6 @@ type JSInfo struct {
 	Now      time.Time       `json:"now"`
 	Disabled bool            `json:"disabled,omitempty"`
 	Config   JetStreamConfig `json:"config,omitempty"`
-	Limits   *JSLimitOpts    `json:"limits,omitempty"`
 	JetStreamStats
 	Streams   int              `json:"streams"`
 	Consumers int              `json:"consumers"`
@@ -2960,8 +2957,6 @@ func (s *Server) Jsz(opts *JSzOptions) (*JSInfo, error) {
 		return jsi, nil
 	}
 
-	jsi.Limits = &s.getOpts().JetStreamLimits
-
 	js.mu.RLock()
 	isLeader := js.cluster == nil || js.cluster.isLeader()
 	js.mu.RUnlock()
@@ -3790,14 +3785,8 @@ func (s *Server) HandleRaftz(w http.ResponseWriter, r *http.Request) {
 
 	gfilter := r.URL.Query().Get("group")
 	afilter := r.URL.Query().Get("acc")
-	if afilter == _EMPTY_ {
-		if sys := s.SystemAccount(); sys != nil {
-			afilter = sys.Name
-		} else {
-			w.WriteHeader(404)
-			w.Write([]byte("System account not found, the server may be shutting down"))
-			return
-		}
+	if afilter == "" {
+		afilter = s.SystemAccount().Name
 	}
 
 	groups := map[string]RaftNode{}
diff --git a/server/opts.go b/server/opts.go
index 70524c48..e717f26e 100644
--- a/server/opts.go
+++ b/server/opts.go
@@ -233,10 +233,10 @@ type RemoteLeafOpts struct {
 }
 
 type JSLimitOpts struct {
-	MaxRequestBatch int           `json:"max_request_batch,omitempty"`
-	MaxAckPending   int           `json:"max_ack_pending,omitempty"`
-	MaxHAAssets     int           `json:"max_ha_assets,omitempty"`
-	Duplicates      time.Duration `json:"max_duplicate_window,omitempty"`
+	MaxRequestBatch int
+	MaxAckPending   int
+	MaxHAAssets     int
+	Duplicates      time.Duration
 }
 
 type JSTpmOpts struct {
@@ -917,13 +917,7 @@ func (o *Options) processConfigFileLine(k string, v any, errors *[]error, warnin
 	case "port":
 		o.Port = int(v.(int64))
 	case "server_name":
-		sn := v.(string)
-		if strings.Contains(sn, " ") {
-			err := &configErr{tk, ErrServerNameHasSpaces.Error()}
-			*errors = append(*errors, err)
-			return
-		}
-		o.ServerName = sn
+		o.ServerName = v.(string)
 	case "host", "net":
 		o.Host = v.(string)
 	case "debug":
@@ -1696,13 +1690,7 @@ func parseCluster(v any, opts *Options, errors *[]error, warnings *[]error) erro
 		tk, mv = unwrapValue(mv, &lt)
 		switch strings.ToLower(mk) {
 		case "name":
-			cn := mv.(string)
-			if strings.Contains(cn, " ") {
-				err := &configErr{tk, ErrClusterNameHasSpaces.Error()}
-				*errors = append(*errors, err)
-				continue
-			}
-			opts.Cluster.Name = cn
+			opts.Cluster.Name = mv.(string)
 		case "listen":
 			hp, err := parseListen(mv)
 			if err != nil {
@@ -1932,13 +1920,7 @@ func parseGateway(v any, o *Options, errors *[]error, warnings *[]error) error {
 		tk, mv = unwrapValue(mv, &lt)
 		switch strings.ToLower(mk) {
 		case "name":
-			gn := mv.(string)
-			if strings.Contains(gn, " ") {
-				err := &configErr{tk, ErrGatewayNameHasSpaces.Error()}
-				*errors = append(*errors, err)
-				continue
-			}
-			o.Gateway.Name = gn
+			o.Gateway.Name = mv.(string)
 		case "listen":
 			hp, err := parseListen(mv)
 			if err != nil {
diff --git a/server/raft.go b/server/raft.go
index 6860f6a2..9c6e5bbb 100644
--- a/server/raft.go
+++ b/server/raft.go
@@ -198,14 +198,15 @@ type raft struct {
 	hcommit   uint64 // The commit at the time that applies were paused
 	pobserver bool   // Whether we were an observer at the time that applies were paused
 
-	prop  *ipQueue[*Entry]               // Proposals
-	entry *ipQueue[*appendEntry]         // Append entries
-	resp  *ipQueue[*appendEntryResponse] // Append entries responses
-	apply *ipQueue[*CommittedEntry]      // Apply queue (committed entries to be passed to upper layer)
-	reqs  *ipQueue[*voteRequest]         // Vote requests
-	votes *ipQueue[*voteResponse]        // Vote responses
-	leadc chan bool                      // Leader changes
-	quit  chan struct{}                  // Raft group shutdown
+	prop     *ipQueue[*Entry]               // Proposals
+	entry    *ipQueue[*appendEntry]         // Append entries
+	resp     *ipQueue[*appendEntryResponse] // Append entries responses
+	apply    *ipQueue[*CommittedEntry]      // Apply queue (committed entries to be passed to upper layer)
+	reqs     *ipQueue[*voteRequest]         // Vote requests
+	votes    *ipQueue[*voteResponse]        // Vote responses
+	stepdown *ipQueue[string]               // Stepdown requests
+	leadc    chan bool                      // Leader changes
+	quit     chan struct{}                  // Raft group shutdown
 }
 
 // cacthupState structure that holds our subscription, and catchup term and index
@@ -390,6 +391,7 @@ func (s *Server) startRaftNode(accName string, cfg *RaftConfig, labels pprofLabe
 		entry:    newIPQueue[*appendEntry](s, qpfx+"appendEntry"),
 		resp:     newIPQueue[*appendEntryResponse](s, qpfx+"appendEntryResponse"),
 		apply:    newIPQueue[*CommittedEntry](s, qpfx+"committedEntry"),
+		stepdown: newIPQueue[string](s, qpfx+"stepdown"),
 		accName:  accName,
 		leadc:    make(chan bool, 32),
 		observer: cfg.Observer,
@@ -497,7 +499,7 @@ func (s *Server) startRaftNode(accName string, cfg *RaftConfig, labels pprofLabe
 	// If we fail to do this for some reason then this is fatal — we cannot
 	// continue setting up or the Raft node may be partially/totally isolated.
 	if err := n.createInternalSubs(); err != nil {
-		n.shutdown(false)
+		n.shutdown(true)
 		return nil, err
 	}
 
@@ -866,7 +868,7 @@ func (n *raft) PauseApply() error {
 
 	// If we are currently a candidate make sure we step down.
 	if n.State() == Candidate {
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 	}
 
 	n.debug("Pausing our apply channel")
@@ -1254,21 +1256,6 @@ func (n *raft) Leader() bool {
 	return n.State() == Leader
 }
 
-// stepdown immediately steps down the Raft node to the
-// follower state. This will take the lock itself.
-func (n *raft) stepdown(newLeader string) {
-	n.Lock()
-	defer n.Unlock()
-	n.stepdownLocked(newLeader)
-}
-
-// stepdownLocked immediately steps down the Raft node to the
-// follower state. This requires the lock is already held.
-func (n *raft) stepdownLocked(newLeader string) {
-	n.debug("Stepping down")
-	n.switchToFollowerLocked(newLeader)
-}
-
 // isCatchingUp returns true if a catchup is currently taking place.
 func (n *raft) isCatchingUp() bool {
 	n.RLock()
@@ -1476,6 +1463,8 @@ func (n *raft) StepDown(preferred ...string) error {
 	n.vote = noVote
 	n.writeTermVote()
 
+	stepdown := n.stepdown
+	prop := n.prop
 	n.Unlock()
 
 	if len(preferred) > 0 && maybeLeader == noLeader {
@@ -1483,18 +1472,15 @@ func (n *raft) StepDown(preferred ...string) error {
 	}
 
 	// If we have a new leader selected, transfer over to them.
-	// Send the append entry directly rather than via the proposals queue,
-	// as we will switch to follower state immediately and will blow away
-	// the contents of the proposal queue in the process.
 	if maybeLeader != noLeader {
-		n.debug("Selected %q for new leader, stepping down due to leadership transfer", maybeLeader)
-		ae := newEntry(EntryLeaderTransfer, []byte(maybeLeader))
-		n.sendAppendEntry([]*Entry{ae})
+		n.debug("Selected %q for new leader", maybeLeader)
+		prop.push(newEntry(EntryLeaderTransfer, []byte(maybeLeader)))
+	} else {
+		// Force us to stepdown here.
+		n.debug("Stepping down")
+		stepdown.push(noLeader)
 	}
 
-	// Force us to stepdown here.
-	n.stepdown(noLeader)
-
 	return nil
 }
 
@@ -1673,7 +1659,7 @@ func (n *raft) shutdown(shouldDelete bool) {
 	queues := []interface {
 		unregister()
 		drain()
-	}{n.reqs, n.votes, n.prop, n.entry, n.resp, n.apply}
+	}{n.reqs, n.votes, n.prop, n.entry, n.resp, n.apply, n.stepdown}
 	for _, q := range queues {
 		q.drain()
 		q.unregister()
@@ -1961,7 +1947,7 @@ func (n *raft) processAppendEntries() {
 // runAsFollower is called by run and will block for as long as the node is
 // running in the follower state.
 func (n *raft) runAsFollower() {
-	for n.State() == Follower {
+	for {
 		elect := n.electTimer()
 
 		select {
@@ -2003,17 +1989,22 @@ func (n *raft) runAsFollower() {
 			n.debug("Ignoring old vote response, we have stepped down")
 			n.votes.popOne()
 		case <-n.resp.ch:
-			// Ignore append entry responses received from before the state change.
-			n.resp.drain()
-		case <-n.prop.ch:
-			// Ignore proposals received from before the state change.
-			n.prop.drain()
+			// We're receiving append entry responses from the network, probably because
+			// we have only just stepped down and they were already in flight. Ignore them.
+			n.resp.popOne()
 		case <-n.reqs.ch:
 			// We've just received a vote request from the network.
 			// Because of drain() it is possible that we get nil from popOne().
 			if voteReq, ok := n.reqs.popOne(); ok {
 				n.processVoteRequest(voteReq)
 			}
+		case <-n.stepdown.ch:
+			// We've received a stepdown request, start following the new leader if
+			// we can.
+			if newLeader, ok := n.stepdown.popOne(); ok {
+				n.switchToFollower(newLeader)
+				return
+			}
 		}
 	}
 }
@@ -2349,7 +2340,7 @@ func (n *raft) runAsLeader() {
 	fsub, err := n.subscribe(psubj, n.handleForwardedProposal)
 	if err != nil {
 		n.warn("Error subscribing to forwarded proposals: %v", err)
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 		n.Unlock()
 		return
 	}
@@ -2357,7 +2348,7 @@ func (n *raft) runAsLeader() {
 	if err != nil {
 		n.warn("Error subscribing to forwarded remove peer proposals: %v", err)
 		n.unsubscribe(fsub)
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 		n.Unlock()
 		return
 	}
@@ -2404,6 +2395,15 @@ func (n *raft) runAsLeader() {
 					n.doRemovePeerAsLeader(string(b.Data))
 				}
 				entries = append(entries, b)
+				// If this is us sending out a leadership transfer stepdown inline here.
+				if b.Type == EntryLeaderTransfer {
+					// Send out what we have and switch to follower.
+					n.sendAppendEntry(entries)
+					n.prop.recycle(&es)
+					n.debug("Stepping down due to leadership transfer")
+					n.switchToFollower(noLeader)
+					return
+				}
 				// Increment size.
 				sz += len(b.Data) + 1
 				// If below thresholds go ahead and send.
@@ -2427,7 +2427,7 @@ func (n *raft) runAsLeader() {
 			}
 		case <-lq.C:
 			if n.lostQuorum() {
-				n.stepdown(noLeader)
+				n.switchToFollower(noLeader)
 				return
 			}
 		case <-n.votes.ch:
@@ -2437,7 +2437,7 @@ func (n *raft) runAsLeader() {
 				continue
 			}
 			if vresp.term > n.Term() {
-				n.stepdown(noLeader)
+				n.switchToFollower(noLeader)
 				return
 			}
 			n.trackPeer(vresp.peer)
@@ -2446,6 +2446,11 @@ func (n *raft) runAsLeader() {
 			if voteReq, ok := n.reqs.popOne(); ok {
 				n.processVoteRequest(voteReq)
 			}
+		case <-n.stepdown.ch:
+			if newLeader, ok := n.stepdown.popOne(); ok {
+				n.switchToFollower(newLeader)
+				return
+			}
 		case <-n.entry.ch:
 			n.processAppendEntries()
 		}
@@ -2616,7 +2621,7 @@ func (n *raft) sendSnapshotToFollower(subject string) (uint64, error) {
 	snap, err := n.loadLastSnapshot()
 	if err != nil {
 		// We need to stepdown here when this happens.
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 		// We need to reset our state here as well.
 		n.resetWAL()
 		return 0, err
@@ -2682,7 +2687,7 @@ func (n *raft) catchupFollower(ar *appendEntryResponse) {
 		n.warn("Request from follower for entry at index [%d] errored for state %+v - %v", start, state, err)
 		if err == ErrStoreEOF {
 			// If we are here we are seeing a request for an item beyond our state, meaning we should stepdown.
-			n.stepdownLocked(noLeader)
+			n.stepdown.push(noLeader)
 			n.Unlock()
 			arPool.Put(ar)
 			return
@@ -2694,7 +2699,7 @@ func (n *raft) catchupFollower(ar *appendEntryResponse) {
 		// If we are here we are seeing a request for an item we do not have, meaning we should stepdown.
 		// This is possible on a reset of our WAL but the other side has a snapshot already.
 		// If we do not stepdown this can cycle.
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 		n.Unlock()
 		arPool.Put(ar)
 		return
@@ -2747,7 +2752,7 @@ func (n *raft) applyCommit(index uint64) error {
 			if err != ErrStoreClosed && err != ErrStoreEOF {
 				n.warn("Got an error loading %d index: %v - will reset", index, err)
 				if n.State() == Leader {
-					n.stepdownLocked(n.selectNextLeader())
+					n.stepdown.push(n.selectNextLeader())
 				}
 				// Reset and cancel any catchup.
 				n.resetWAL()
@@ -2824,7 +2829,7 @@ func (n *raft) applyCommit(index uint64) error {
 
 			// If this is us and we are the leader we should attempt to stepdown.
 			if peer == n.id && n.State() == Leader {
-				n.stepdown(n.selectNextLeader())
+				n.stepdown.push(n.selectNextLeader())
 			}
 
 			// Remove from string intern map.
@@ -2955,17 +2960,14 @@ func (n *raft) runAsCandidate() {
 		n.ID(): {},
 	}
 
-	for n.State() == Candidate {
+	for {
 		elect := n.electTimer()
 		select {
 		case <-n.entry.ch:
 			n.processAppendEntries()
 		case <-n.resp.ch:
-			// Ignore append entry responses received from before the state change.
-			n.resp.drain()
-		case <-n.prop.ch:
-			// Ignore proposals received from before the state change.
-			n.prop.drain()
+			// Ignore
+			n.resp.popOne()
 		case <-n.s.quitCh:
 			n.shutdown(false)
 			return
@@ -3001,8 +3003,8 @@ func (n *raft) runAsCandidate() {
 				n.term = vresp.term
 				n.vote = noVote
 				n.writeTermVote()
+				n.stepdown.push(noLeader)
 				n.lxfer = false
-				n.stepdownLocked(noLeader)
 				n.Unlock()
 			}
 		case <-n.reqs.ch:
@@ -3010,6 +3012,11 @@ func (n *raft) runAsCandidate() {
 			if voteReq, ok := n.reqs.popOne(); ok {
 				n.processVoteRequest(voteReq)
 			}
+		case <-n.stepdown.ch:
+			if newLeader, ok := n.stepdown.popOne(); ok {
+				n.switchToFollower(newLeader)
+				return
+			}
 		}
 	}
 }
@@ -3170,7 +3177,7 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) {
 				n.writeTermVote()
 			}
 			n.debug("Received append entry from another leader, stepping down to %q", ae.leader)
-			n.stepdownLocked(ae.leader)
+			n.stepdown.push(ae.leader)
 		} else {
 			// Let them know we are the leader.
 			ar := newAppendEntryResponse(n.term, n.pindex, n.id, false)
@@ -3194,12 +3201,12 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) {
 			// If the append entry term is newer than the current term, erase our
 			// vote.
 			if ae.term > n.term {
-				n.term = ae.term
 				n.vote = noVote
-				n.writeTermVote()
 			}
 			n.debug("Received append entry in candidate state from %q, converting to follower", ae.leader)
-			n.stepdownLocked(ae.leader)
+			n.term = ae.term
+			n.writeTermVote()
+			n.stepdown.push(ae.leader)
 		}
 	}
 
@@ -3262,12 +3269,8 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) {
 		}
 		if n.State() != Follower {
 			n.debug("Term higher than ours and we are not a follower: %v, stepping down to %q", n.State(), ae.leader)
-			n.stepdownLocked(ae.leader)
+			n.stepdown.push(ae.leader)
 		}
-	} else if ae.term < n.term && !catchingUp && isNew {
-		n.debug("Ignoring AppendEntry from a leader (%s) with term %d which is less than ours", ae.leader, ae.term)
-		n.Unlock()
-		return
 	}
 
 	if isNew && n.leader != ae.leader && n.State() == Follower {
@@ -3375,6 +3378,8 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) {
 
 		} else {
 			n.debug("AppendEntry did not match %d %d with %d %d", ae.pterm, ae.pindex, n.pterm, n.pindex)
+			// Reset our term.
+			n.term = n.pterm
 			if ae.pindex > n.pindex {
 				// Setup our state for catching up.
 				inbox := n.createCatchup(ae)
@@ -3520,7 +3525,7 @@ func (n *raft) processAppendEntryResponse(ar *appendEntryResponse) {
 		n.vote = noVote
 		n.writeTermVote()
 		n.warn("Detected another leader with higher term, will stepdown and reset")
-		n.stepdownLocked(noLeader)
+		n.stepdown.push(noLeader)
 		n.resetWAL()
 		n.Unlock()
 		arPool.Put(ar)
@@ -3568,7 +3573,7 @@ func (n *raft) storeToWAL(ae *appendEntry) error {
 	if index := ae.pindex + 1; index != seq {
 		n.warn("Wrong index, ae is %+v, index stored was %d, n.pindex is %d, will reset", ae, seq, n.pindex)
 		if n.State() == Leader {
-			n.stepdownLocked(n.selectNextLeader())
+			n.stepdown.push(n.selectNextLeader())
 		}
 		// Reset and cancel any catchup.
 		n.resetWAL()
@@ -3968,9 +3973,9 @@ func (n *raft) processVoteRequest(vr *voteRequest) error {
 		if n.State() != Follower {
 			n.debug("Stepping down from %s, detected higher term: %d vs %d",
 				strings.ToLower(n.State().String()), vr.term, n.term)
-			n.stepdownLocked(noLeader)
+			n.stepdown.push(noLeader)
+			n.term = vr.term
 		}
-		n.term = vr.term
 		n.vote = noVote
 		n.writeTermVote()
 	}
@@ -4084,9 +4089,8 @@ func (n *raft) switchState(state RaftState) {
 
 	if pstate == Leader && state != Leader {
 		n.updateLeadChange(false)
-		// Drain the append entry response and proposal queues.
+		// Drain the response queue.
 		n.resp.drain()
-		n.prop.drain()
 	} else if state == Leader && pstate != Leader {
 		if len(n.pae) > 0 {
 			n.pae = make(map[uint64]*appendEntry)
@@ -4103,17 +4107,13 @@ const (
 )
 
 func (n *raft) switchToFollower(leader string) {
-	n.Lock()
-	defer n.Unlock()
-
-	n.switchToFollowerLocked(leader)
-}
-
-func (n *raft) switchToFollowerLocked(leader string) {
 	if n.State() == Closed {
 		return
 	}
 
+	n.Lock()
+	defer n.Unlock()
+
 	n.debug("Switching to follower")
 
 	n.lxfer = false
diff --git a/server/route.go b/server/route.go
index ca4d2bbb..7bbcccdd 100644
--- a/server/route.go
+++ b/server/route.go
@@ -82,9 +82,6 @@ type route struct {
 	// Selected compression mode, which may be different from the
 	// server configured mode.
 	compression string
-	// Transient value used to set the Info.NoGossip when initiating
-	// an implicit route and sending to the remote.
-	noGossip bool
 }
 
 type connectInfo struct {
@@ -687,15 +684,12 @@ func (c *client) processRouteInfo(info *Info) {
 		return
 	}
 
-	var sendDelayedInfo bool
-
 	// First INFO, check if this server is configured for compression because
 	// if that is the case, we need to negotiate it with the remote server.
 	if needsCompression(opts.Cluster.Compression.Mode) {
 		accName := bytesToString(c.route.accName)
 		// If we did not yet negotiate...
-		compNeg := c.flags.isSet(compressionNegotiated)
-		if !compNeg {
+		if !c.flags.isSet(compressionNegotiated) {
 			// Prevent from getting back here.
 			c.flags.set(compressionNegotiated)
 			// Release client lock since following function will need server lock.
@@ -712,21 +706,24 @@ func (c *client) processRouteInfo(info *Info) {
 			}
 			// No compression because one side does not want/can't, so proceed.
 			c.mu.Lock()
-			// Check that the connection did not close if the lock was released.
-			if c.isClosed() {
+		} else if didSolicit {
+			// The other side has switched to compression, so we can now set
+			// the first ping timer and send the delayed INFO for situations
+			// where it was not already sent.
+			c.setFirstPingTimer()
+			if !routeShouldDelayInfo(accName, opts) {
+				cm := compressionModeForInfoProtocol(&opts.Cluster.Compression, c.route.compression)
+				// Need to release and then reacquire...
 				c.mu.Unlock()
-				return
+				s.sendDelayedRouteInfo(c, accName, cm)
+				c.mu.Lock()
 			}
 		}
-		// We can set the ping timer after we just negotiated compression above,
-		// or for solicited routes if we already negotiated.
-		if !compNeg || didSolicit {
-			c.setFirstPingTimer()
+		// Check that the connection did not close if the lock was released.
+		if c.isClosed() {
+			c.mu.Unlock()
+			return
 		}
-		// When compression is configured, we delay the initial INFO for any
-		// solicited route. So we need to send the delayed INFO simply based
-		// on the didSolicit boolean.
-		sendDelayedInfo = didSolicit
 	} else {
 		// Coming from an old server, the Compression field would be the empty
 		// string. For servers that are configured with CompressionNotSupported,
@@ -736,10 +733,6 @@ func (c *client) processRouteInfo(info *Info) {
 		} else {
 			c.route.compression = CompressionOff
 		}
-		// When compression is not configured, we delay the initial INFO only
-		// for solicited pooled routes, so use the same check that we did when
-		// we decided to delay in createRoute().
-		sendDelayedInfo = didSolicit && routeShouldDelayInfo(bytesToString(c.route.accName), opts)
 	}
 
 	// Mark that the INFO protocol has been received, so we can detect updates.
@@ -817,15 +810,11 @@ func (c *client) processRouteInfo(info *Info) {
 	}
 	accName := string(c.route.accName)
 
-	// Capture the noGossip value and reset it here.
-	noGossip := c.route.noGossip
-	c.route.noGossip = false
-
 	// Check to see if we have this remote already registered.
 	// This can happen when both servers have routes to each other.
 	c.mu.Unlock()
 
-	if added := s.addRoute(c, didSolicit, sendDelayedInfo, noGossip, info, accName); added {
+	if added := s.addRoute(c, didSolicit, info, accName); added {
 		if accName != _EMPTY_ {
 			c.Debugf("Registering remote route %q for account %q", info.ID, accName)
 		} else {
@@ -859,7 +848,7 @@ func (s *Server) negotiateRouteCompression(c *client, didSolicit bool, accName,
 	if needsCompression(cm) {
 		// Generate an INFO with the chosen compression mode.
 		s.mu.Lock()
-		infoProto := s.generateRouteInitialInfoJSON(accName, cm, 0, false)
+		infoProto := s.generateRouteInitialInfoJSON(accName, cm, 0)
 		s.mu.Unlock()
 
 		// If we solicited, then send this INFO protocol BEFORE switching
@@ -888,9 +877,29 @@ func (s *Server) negotiateRouteCompression(c *client, didSolicit bool, accName,
 		c.mu.Unlock()
 		return true, nil
 	}
+	// We are not using compression, set the ping timer.
+	c.mu.Lock()
+	c.setFirstPingTimer()
+	c.mu.Unlock()
+	// If this is a solicited route, we need to send the INFO if it was not
+	// done during createRoute() and will not be done in addRoute().
+	if didSolicit && !routeShouldDelayInfo(accName, opts) {
+		cm = compressionModeForInfoProtocol(&opts.Cluster.Compression, cm)
+		s.sendDelayedRouteInfo(c, accName, cm)
+	}
 	return false, nil
 }
 
+func (s *Server) sendDelayedRouteInfo(c *client, accName, cm string) {
+	s.mu.Lock()
+	infoProto := s.generateRouteInitialInfoJSON(accName, cm, 0)
+	s.mu.Unlock()
+
+	c.mu.Lock()
+	c.enqueueProto(infoProto)
+	c.mu.Unlock()
+}
+
 // Possibly sends local subscriptions interest to this route
 // based on changes in the remote's Export permissions.
 func (s *Server) updateRemoteRoutePerms(c *client, info *Info) {
@@ -1026,7 +1035,7 @@ func (s *Server) processImplicitRoute(info *Info, routeNoPool bool) {
 	if info.AuthRequired {
 		r.User = url.UserPassword(opts.Cluster.Username, opts.Cluster.Password)
 	}
-	s.startGoRoutine(func() { s.connectToRoute(r, Implicit, true, info.NoGossip, info.RouteAccount) })
+	s.startGoRoutine(func() { s.connectToRoute(r, false, true, info.RouteAccount) })
 	// If we are processing an implicit route from a route that does not
 	// support pooling/pinned-accounts, we won't receive an INFO for each of
 	// the pinned-accounts that we would normally receive. In that case, just
@@ -1036,7 +1045,7 @@ func (s *Server) processImplicitRoute(info *Info, routeNoPool bool) {
 		rURL := r
 		for _, an := range opts.Cluster.PinnedAccounts {
 			accName := an
-			s.startGoRoutine(func() { s.connectToRoute(rURL, Implicit, true, info.NoGossip, accName) })
+			s.startGoRoutine(func() { s.connectToRoute(rURL, false, true, accName) })
 		}
 	}
 }
@@ -1088,39 +1097,11 @@ func (s *Server) forwardNewRouteInfoToKnownServers(info *Info) {
 	b, _ := json.Marshal(info)
 	infoJSON := []byte(fmt.Sprintf(InfoProto, b))
 
-	// If this is for a pinned account, we will try to send the gossip
-	// through our pinned account routes, but fall back to the other
-	// routes in case we don't have one for a given remote.
-	accRemotes := map[string]struct{}{}
-	if info.RouteAccount != _EMPTY_ {
-		if remotes, ok := s.accRoutes[info.RouteAccount]; ok {
-			for remoteID, r := range remotes {
-				if r == nil {
-					continue
-				}
-				accRemotes[remoteID] = struct{}{}
-				r.mu.Lock()
-				// Do not send to a remote that does not support pooling/pinned-accounts.
-				if remoteID != info.ID && !r.route.noPool {
-					r.enqueueProto(infoJSON)
-				}
-				r.mu.Unlock()
-			}
-		}
-	}
-
 	s.forEachRemote(func(r *client) {
 		r.mu.Lock()
-		remoteID := r.route.remoteID
-		if info.RouteAccount != _EMPTY_ {
-			if _, processed := accRemotes[remoteID]; processed {
-				r.mu.Unlock()
-				return
-			}
-		}
 		// If this is a new route for a given account, do not send to a server
 		// that does not support pooling/pinned-accounts.
-		if remoteID != info.ID &&
+		if r.route.remoteID != info.ID &&
 			(info.RouteAccount == _EMPTY_ || (info.RouteAccount != _EMPTY_ && !r.route.noPool)) {
 			r.enqueueProto(infoJSON)
 		}
@@ -1699,12 +1680,17 @@ func (c *client) sendRouteSubOrUnSubProtos(subs []*subscription, isSubProto, tra
 	c.enqueueProto(buf)
 }
 
-func (s *Server) createRoute(conn net.Conn, rURL *url.URL, rtype RouteType, noGossip bool, accName string) *client {
+func (s *Server) createRoute(conn net.Conn, rURL *url.URL, accName string) *client {
 	// Snapshot server options.
 	opts := s.getOpts()
 
 	didSolicit := rURL != nil
-	r := &route{routeType: rtype, didSolicit: didSolicit, poolIdx: -1, noGossip: noGossip}
+	r := &route{didSolicit: didSolicit, poolIdx: -1}
+	for _, route := range opts.Routes {
+		if rURL != nil && (strings.EqualFold(rURL.Host, route.Host)) {
+			r.routeType = Explicit
+		}
+	}
 
 	c := &client{srv: s, nc: conn, opts: ClientOpts{}, kind: ROUTER, msubs: -1, mpay: -1, route: r, start: time.Now()}
 
@@ -1721,7 +1707,7 @@ func (s *Server) createRoute(conn net.Conn, rURL *url.URL, rtype RouteType, noGo
 	// the incoming INFO from the remote. Also delay if configured for compression.
 	delayInfo := didSolicit && (compressionConfigured || routeShouldDelayInfo(accName, opts))
 	if !delayInfo {
-		infoJSON = s.generateRouteInitialInfoJSON(accName, opts.Cluster.Compression.Mode, 0, noGossip)
+		infoJSON = s.generateRouteInitialInfoJSON(accName, opts.Cluster.Compression.Mode, 0)
 	}
 	authRequired := s.routeInfo.AuthRequired
 	tlsRequired := s.routeInfo.TLSRequired
@@ -1854,7 +1840,7 @@ func routeShouldDelayInfo(accName string, opts *Options) bool {
 // To be used only when a route is created (to send the initial INFO protocol).
 //
 // Server lock held on entry.
-func (s *Server) generateRouteInitialInfoJSON(accName, compression string, poolIdx int, noGossip bool) []byte {
+func (s *Server) generateRouteInitialInfoJSON(accName, compression string, poolIdx int) []byte {
 	// New proto wants a nonce (although not used in routes, that is, not signed in CONNECT)
 	var raw [nonceLen]byte
 	nonce := raw[:]
@@ -1864,11 +1850,11 @@ func (s *Server) generateRouteInitialInfoJSON(accName, compression string, poolI
 	if s.getOpts().Cluster.Compression.Mode == CompressionS2Auto {
 		compression = CompressionS2Auto
 	}
-	ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression, ri.NoGossip = string(nonce), accName, poolIdx, compression, noGossip
+	ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression = string(nonce), accName, poolIdx, compression
 	infoJSON := generateInfoJSON(&s.routeInfo)
 	// Clear now that it has been serialized. Will prevent nonce to be included in async INFO that we may send.
 	// Same for some other fields.
-	ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression, ri.NoGossip = _EMPTY_, _EMPTY_, 0, _EMPTY_, false
+	ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression = _EMPTY_, _EMPTY_, 0, _EMPTY_
 	return infoJSON
 }
 
@@ -1877,7 +1863,7 @@ const (
 	_EMPTY_ = ""
 )
 
-func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool, info *Info, accName string) bool {
+func (s *Server) addRoute(c *client, didSolicit bool, info *Info, accName string) bool {
 	id := info.ID
 
 	var acc *Account
@@ -1963,19 +1949,12 @@ func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool,
 			c.mu.Lock()
 			idHash := c.route.idHash
 			cid := c.cid
-			if sendDelayedInfo {
-				cm := compressionModeForInfoProtocol(&opts.Cluster.Compression, c.route.compression)
-				c.enqueueProto(s.generateRouteInitialInfoJSON(accName, cm, 0, noGossip))
-			}
 			if c.last.IsZero() {
 				c.last = time.Now()
 			}
 			if acc != nil {
 				c.acc = acc
 			}
-			// This will be true if this is a route that was initiated from the
-			// gossip protocol (basically invoked from processImplicitRoute).
-			fromGossip := didSolicit && c.route.routeType == Implicit
 			c.mu.Unlock()
 
 			// Store this route with key being the route id hash + account name
@@ -1984,20 +1963,8 @@ func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool,
 			// Now that we have registered the route, we can remove from the temp map.
 			s.removeFromTempClients(cid)
 
-			// We will not gossip if we are an implicit route created due to
-			// gossip, or if the remote instructed us not to gossip.
-			if !fromGossip && !info.NoGossip {
-				if !didSolicit {
-					// If the connection was accepted, instruct the neighbors to
-					// set Info.NoGossip to true also when sending their own INFO
-					// protocol. In normal situations, any implicit route would
-					// set their Info.NoGossip to true, but we do this to solve
-					// a very specific situation. For some background, see test
-					// TestRouteImplicitJoinsSeparateGroups.
-					info.NoGossip = true
-				}
-				s.forwardNewRouteInfoToKnownServers(info)
-			}
+			// Notify other routes about this new route
+			s.forwardNewRouteInfoToKnownServers(info)
 
 			// Send subscription interest
 			s.sendSubsToRoute(c, -1, accName)
@@ -2078,9 +2045,9 @@ func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool,
 		rHash := c.route.hash
 		rn := c.route.remoteName
 		url := c.route.url
-		if sendDelayedInfo {
-			cm := compressionModeForInfoProtocol(&opts.Cluster.Compression, c.route.compression)
-			c.enqueueProto(s.generateRouteInitialInfoJSON(_EMPTY_, cm, idx, noGossip))
+		// For solicited routes, we need now to send the INFO protocol.
+		if didSolicit {
+			c.enqueueProto(s.generateRouteInitialInfoJSON(_EMPTY_, c.route.compression, idx))
 		}
 		if c.last.IsZero() {
 			c.last = time.Now()
@@ -2118,13 +2085,8 @@ func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool,
 			}
 
 			// we don't need to send if the only route is the one we just accepted.
-			// For other checks, see other call to forwardNewRouteInfoToKnownServers
-			// in the handling of pinned account above.
-			fromGossip := didSolicit && rtype == Implicit
-			if len(s.routes) > 1 && !fromGossip && !info.NoGossip {
-				if !didSolicit {
-					info.NoGossip = true
-				}
+			if len(s.routes) > 1 {
+				// Now let the known servers know about this new route
 				s.forwardNewRouteInfoToKnownServers(info)
 			}
 
@@ -2160,7 +2122,7 @@ func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo, noGossip bool,
 					s.grWG.Done()
 					return
 				}
-				s.connectToRoute(url, rtype, true, noGossip, _EMPTY_)
+				s.connectToRoute(url, rtype == Explicit, true, _EMPTY_)
 			})
 		}
 	}
@@ -2562,7 +2524,7 @@ func (s *Server) startRouteAcceptLoop() {
 	}
 
 	// Start the accept loop in a different go routine.
-	go s.acceptConnections(l, "Route", func(conn net.Conn) { s.createRoute(conn, nil, Implicit, false, _EMPTY_) }, nil)
+	go s.acceptConnections(l, "Route", func(conn net.Conn) { s.createRoute(conn, nil, _EMPTY_) }, nil)
 
 	// Solicit Routes if applicable. This will not block.
 	s.solicitRoutes(opts.Routes, opts.Cluster.PinnedAccounts)
@@ -2604,13 +2566,14 @@ func (s *Server) StartRouting(clientListenReady chan struct{}) {
 }
 
 func (s *Server) reConnectToRoute(rURL *url.URL, rtype RouteType, accName string) {
+	tryForEver := rtype == Explicit
 	// If A connects to B, and B to A (regardless if explicit or
 	// implicit - due to auto-discovery), and if each server first
 	// registers the route on the opposite TCP connection, the
 	// two connections will end-up being closed.
 	// Add some random delay to reduce risk of repeated failures.
 	delay := time.Duration(rand.Intn(100)) * time.Millisecond
-	if rtype == Explicit {
+	if tryForEver {
 		delay += DEFAULT_ROUTE_RECONNECT
 	}
 	select {
@@ -2619,7 +2582,7 @@ func (s *Server) reConnectToRoute(rURL *url.URL, rtype RouteType, accName string
 		s.grWG.Done()
 		return
 	}
-	s.connectToRoute(rURL, rtype, false, false, accName)
+	s.connectToRoute(rURL, tryForEver, false, accName)
 }
 
 // Checks to make sure the route is still valid.
@@ -2632,26 +2595,21 @@ func (s *Server) routeStillValid(rURL *url.URL) bool {
 	return false
 }
 
-func (s *Server) connectToRoute(rURL *url.URL, rtype RouteType, firstConnect, noGossip bool, accName string) {
-	defer s.grWG.Done()
-	if rURL == nil {
-		return
-	}
-	// For explicit routes, we will try to connect until we succeed. For implicit
-	// we will try only based on the number of ConnectRetries optin.
-	tryForEver := rtype == Explicit
-
+func (s *Server) connectToRoute(rURL *url.URL, tryForEver, firstConnect bool, accName string) {
 	// Snapshot server options.
 	opts := s.getOpts()
 
+	defer s.grWG.Done()
+
 	const connErrFmt = "Error trying to connect to route (attempt %v): %v"
 
-	s.mu.RLock()
+	s.mu.Lock()
 	resolver := s.routeResolver
 	excludedAddresses := s.routesToSelf
-	s.mu.RUnlock()
+	s.mu.Unlock()
 
-	for attempts := 0; s.isRunning(); {
+	attempts := 0
+	for s.isRunning() && rURL != nil {
 		if tryForEver {
 			if !s.routeStillValid(rURL) {
 				return
@@ -2705,7 +2663,7 @@ func (s *Server) connectToRoute(rURL *url.URL, rtype RouteType, firstConnect, no
 
 		// We have a route connection here.
 		// Go ahead and create it and exit this func.
-		s.createRoute(conn, rURL, rtype, noGossip, accName)
+		s.createRoute(conn, rURL, accName)
 		return
 	}
 }
@@ -2734,13 +2692,13 @@ func (s *Server) solicitRoutes(routes []*url.URL, accounts []string) {
 	s.saveRouteTLSName(routes)
 	for _, r := range routes {
 		route := r
-		s.startGoRoutine(func() { s.connectToRoute(route, Explicit, true, false, _EMPTY_) })
+		s.startGoRoutine(func() { s.connectToRoute(route, true, true, _EMPTY_) })
 	}
 	// Now go over possible per-account routes and create them.
 	for _, an := range accounts {
 		for _, r := range routes {
 			route, accName := r, an
-			s.startGoRoutine(func() { s.connectToRoute(route, Explicit, true, false, accName) })
+			s.startGoRoutine(func() { s.connectToRoute(route, true, true, accName) })
 		}
 	}
 }
@@ -2862,7 +2820,7 @@ func (s *Server) removeRoute(c *client) {
 		opts          = s.getOpts()
 		rURL          *url.URL
 		noPool        bool
-		rtype         RouteType
+		didSolicit    bool
 	)
 	c.mu.Lock()
 	cid := c.cid
@@ -2881,7 +2839,7 @@ func (s *Server) removeRoute(c *client) {
 		connectURLs = r.connectURLs
 		wsConnectURLs = r.wsConnURLs
 		rURL = r.url
-		rtype = r.routeType
+		didSolicit = r.didSolicit
 	}
 	c.mu.Unlock()
 	if accName != _EMPTY_ {
@@ -2944,12 +2902,12 @@ func (s *Server) removeRoute(c *client) {
 			// this remote was a "no pool" route, attempt to reconnect.
 			if noPool {
 				if s.routesPoolSize > 1 {
-					s.startGoRoutine(func() { s.connectToRoute(rURL, rtype, true, false, _EMPTY_) })
+					s.startGoRoutine(func() { s.connectToRoute(rURL, didSolicit, true, _EMPTY_) })
 				}
 				if len(opts.Cluster.PinnedAccounts) > 0 {
 					for _, an := range opts.Cluster.PinnedAccounts {
 						accName := an
-						s.startGoRoutine(func() { s.connectToRoute(rURL, rtype, true, false, accName) })
+						s.startGoRoutine(func() { s.connectToRoute(rURL, didSolicit, true, accName) })
 					}
 				}
 			}
diff --git a/server/server.go b/server/server.go
index 6d8a6064..4f26b86a 100644
--- a/server/server.go
+++ b/server/server.go
@@ -141,7 +141,6 @@ type Info struct {
 	RoutePoolIdx  int                `json:"route_pool_idx,omitempty"`
 	RouteAccount  string             `json:"route_account,omitempty"`
 	RouteAccReqID string             `json:"route_acc_add_reqid,omitempty"`
-	NoGossip      bool               `json:"no_gossip,omitempty"`
 
 	// Gateways Specific
 	Gateway           string   `json:"gateway,omitempty"`             // Name of the origin Gateway (sent by gateway's INFO)
@@ -1005,9 +1004,6 @@ func (s *Server) ClientURL() string {
 }
 
 func validateCluster(o *Options) error {
-	if o.Cluster.Name != _EMPTY_ && strings.Contains(o.Cluster.Name, " ") {
-		return ErrClusterNameHasSpaces
-	}
 	if o.Cluster.Compression.Mode != _EMPTY_ {
 		if err := validateAndNormalizeCompressionOption(&o.Cluster.Compression, CompressionS2Fast); err != nil {
 			return err
@@ -1017,9 +1013,8 @@ func validateCluster(o *Options) error {
 		return fmt.Errorf("cluster: %v", err)
 	}
 	// Check that cluster name if defined matches any gateway name.
-	// Note that we have already verified that the gateway name does not have spaces.
-	if o.Gateway.Name != _EMPTY_ && o.Gateway.Name != o.Cluster.Name {
-		if o.Cluster.Name != _EMPTY_ {
+	if o.Gateway.Name != "" && o.Gateway.Name != o.Cluster.Name {
+		if o.Cluster.Name != "" {
 			return ErrClusterNameConfigConflict
 		}
 		// Set this here so we do not consider it dynamic.
@@ -1060,9 +1055,6 @@ func validateOptions(o *Options) error {
 		return fmt.Errorf("max_payload (%v) cannot be higher than max_pending (%v)",
 			o.MaxPayload, o.MaxPending)
 	}
-	if o.ServerName != _EMPTY_ && strings.Contains(o.ServerName, " ") {
-		return errors.New("server name cannot contain spaces")
-	}
 	// Check that the trust configuration is correct.
 	if err := validateTrustedOperators(o); err != nil {
 		return err
@@ -4158,16 +4150,6 @@ func (s *Server) isLameDuckMode() bool {
 	return s.ldm
 }
 
-// LameDuckShutdown will perform a lame duck shutdown of NATS, whereby
-// the client listener is closed, existing client connections are
-// kicked, Raft leaderships are transferred, JetStream is shutdown
-// and then finally shutdown the the NATS Server itself.
-// This function blocks and will not return until the NATS Server
-// has completed the entire shutdown operation.
-func (s *Server) LameDuckShutdown() {
-	s.lameDuckMode()
-}
-
 // This function will close the client listener then close the clients
 // at some interval to avoid a reconnect storm.
 // We will also transfer any raft leaders and shutdown JetStream.
diff --git a/server/stream.go b/server/stream.go
index 545a1dac..8bbcc9aa 100644
--- a/server/stream.go
+++ b/server/stream.go
@@ -1306,15 +1306,9 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 		}
 		// Check subject filters overlap.
 		for outer, tr := range cfg.Mirror.SubjectTransforms {
-			if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {
-				return StreamConfig{}, NewJSMirrorInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source))
+			if !IsValidSubject(tr.Source) {
+				return StreamConfig{}, NewJSMirrorInvalidSubjectFilterError()
 			}
-
-			err := ValidateMapping(tr.Source, tr.Destination)
-			if err != nil {
-				return StreamConfig{}, NewJSMirrorInvalidTransformDestinationError(err)
-			}
-
 			for inner, innertr := range cfg.Mirror.SubjectTransforms {
 				if inner != outer && SubjectsCollide(tr.Source, innertr.Source) {
 					return StreamConfig{}, NewJSMirrorOverlappingSubjectFiltersError()
@@ -1356,10 +1350,10 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 			if cfg.Mirror.External.DeliverPrefix != _EMPTY_ {
 				deliveryPrefixes = append(deliveryPrefixes, cfg.Mirror.External.DeliverPrefix)
 			}
-
 			if cfg.Mirror.External.ApiPrefix != _EMPTY_ {
 				apiPrefixes = append(apiPrefixes, cfg.Mirror.External.ApiPrefix)
 			}
+
 		}
 	}
 
@@ -1392,18 +1386,17 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 			}
 
 			for _, tr := range src.SubjectTransforms {
-				if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {
-					return StreamConfig{}, NewJSSourceInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source))
-				}
-
-				err := ValidateMapping(tr.Source, tr.Destination)
+				err := ValidateMappingDestination(tr.Destination)
 				if err != nil {
-					return StreamConfig{}, NewJSSourceInvalidTransformDestinationError(err)
+					return StreamConfig{}, NewJSSourceInvalidTransformDestinationError()
 				}
 			}
 
 			// Check subject filters overlap.
 			for outer, tr := range src.SubjectTransforms {
+				if !IsValidSubject(tr.Source) {
+					return StreamConfig{}, NewJSSourceInvalidSubjectFilterError()
+				}
 				for inner, innertr := range src.SubjectTransforms {
 					if inner != outer && subjectIsSubsetMatch(tr.Source, innertr.Source) {
 						return StreamConfig{}, NewJSSourceOverlappingSubjectFiltersError()
@@ -1584,18 +1577,6 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 		}
 	}
 
-	// Check the subject transform if any
-	if cfg.SubjectTransform != nil {
-		if cfg.SubjectTransform.Source != _EMPTY_ && !IsValidSubject(cfg.SubjectTransform.Source) {
-			return StreamConfig{}, NewJSStreamTransformInvalidSourceError(fmt.Errorf("%w %s", ErrBadSubject, cfg.SubjectTransform.Source))
-		}
-
-		err := ValidateMapping(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
-		if err != nil {
-			return StreamConfig{}, NewJSStreamTransformInvalidDestinationError(err)
-		}
-	}
-
 	return cfg, nil
 }
 
diff --git a/server/stree/stree.go b/server/stree/stree.go
index d0835bf5..fd72b3ba 100644
--- a/server/stree/stree.go
+++ b/server/stree/stree.go
@@ -51,10 +51,6 @@ func (t *SubjectTree[T]) Empty() *SubjectTree[T] {
 
 // Insert a value into the tree. Will return if the value was updated and if so the old value.
 func (t *SubjectTree[T]) Insert(subject []byte, value T) (*T, bool) {
-	if t == nil {
-		return nil, false
-	}
-
 	old, updated := t.insert(&t.root, subject, value, 0)
 	if !updated {
 		t.size++
@@ -64,10 +60,6 @@ func (t *SubjectTree[T]) Insert(subject []byte, value T) (*T, bool) {
 
 // Find will find the value and return it or false if it was not found.
 func (t *SubjectTree[T]) Find(subject []byte) (*T, bool) {
-	if t == nil {
-		return nil, false
-	}
-
 	var si int
 	for n := t.root; n != nil; {
 		if n.isLeaf() {
@@ -96,10 +88,6 @@ func (t *SubjectTree[T]) Find(subject []byte) (*T, bool) {
 
 // Delete will delete the item and return its value, or not found if it did not exist.
 func (t *SubjectTree[T]) Delete(subject []byte) (*T, bool) {
-	if t == nil {
-		return nil, false
-	}
-
 	val, deleted := t.delete(&t.root, subject, 0)
 	if deleted {
 		t.size--
@@ -109,7 +97,7 @@ func (t *SubjectTree[T]) Delete(subject []byte) (*T, bool) {
 
 // Match will match against a subject that can have wildcards and invoke the callback func for each matched value.
 func (t *SubjectTree[T]) Match(filter []byte, cb func(subject []byte, val *T)) {
-	if t == nil || t.root == nil || len(filter) == 0 || cb == nil {
+	if len(filter) == 0 || cb == nil {
 		return
 	}
 	// We need to break this up into chunks based on wildcards, either pwc '*' or fwc '>'.
diff --git a/server/sublist.go b/server/sublist.go
index c0e7a181..0000ad9f 100644
--- a/server/sublist.go
+++ b/server/sublist.go
@@ -1225,12 +1225,12 @@ func isValidLiteralSubject(tokens []string) bool {
 	return true
 }
 
-// ValidateMapping returns nil error if the subject is a valid subject mapping destination subject
-func ValidateMapping(src string, dest string) error {
-	if dest == _EMPTY_ {
+// ValidateMappingDestination returns nil error if the subject is a valid subject mapping destination subject
+func ValidateMappingDestination(subject string) error {
+	if subject == _EMPTY_ {
 		return nil
 	}
-	subjectTokens := strings.Split(dest, tsep)
+	subjectTokens := strings.Split(subject, tsep)
 	sfwc := false
 	for _, t := range subjectTokens {
 		length := len(t)
@@ -1238,7 +1238,6 @@ func ValidateMapping(src string, dest string) error {
 			return &mappingDestinationErr{t, ErrInvalidMappingDestinationSubject}
 		}
 
-		// if it looks like it contains a mapping function, it should be a valid mapping function
 		if length > 4 && t[0] == '{' && t[1] == '{' && t[length-2] == '}' && t[length-1] == '}' {
 			if !partitionMappingFunctionRegEx.MatchString(t) &&
 				!wildcardMappingFunctionRegEx.MatchString(t) &&
@@ -1259,10 +1258,7 @@ func ValidateMapping(src string, dest string) error {
 			return ErrInvalidMappingDestinationSubject
 		}
 	}
-
-	// Finally, verify that the transform can actually be created from the source and destination
-	_, err := NewSubjectTransform(src, dest)
-	return err
+	return nil
 }
 
 // Will check tokens and report back if the have any partial or full wildcards.


Test patch:
diff --git a/scripts/runTestsOnTravis.sh b/scripts/runTestsOnTravis.sh
index eb1fe80a..6d2b8f37 100755
--- a/scripts/runTestsOnTravis.sh
+++ b/scripts/runTestsOnTravis.sh
@@ -10,7 +10,7 @@ if [ "$1" = "compile" ]; then
     go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1;
     golangci-lint run;
     if [ "$TRAVIS_TAG" != "" ]; then
-        go test -race -v -run=TestVersionMatchesTag ./server -ldflags="-X=github.com/nats-io/nats-server/v2/server.serverVersion=$TRAVIS_TAG" -count=1 -vet=off
+        go test -race -v -run=TestVersionMatchesTag ./server -count=1 -vet=off
     fi
 
 elif [ "$1" = "build_only" ]; then
@@ -100,8 +100,7 @@ elif [ "$1" = "srv_pkg_non_js_tests" ]; then
     # by using `skip_js_tests`, MQTT tests by using `skip_mqtt_tests` and
     # message tracing tests by using `skip_msgtrace_tests`.
 
-    # Also including the ldflag with the version since this includes the `TestVersionMatchesTag`.
-    go test -race -v -p=1 ./server/... -ldflags="-X=github.com/nats-io/nats-server/v2/server.serverVersion=$TRAVIS_TAG" -tags=skip_store_tests,skip_js_tests,skip_mqtt_tests,skip_msgtrace_tests -count=1 -vet=off -timeout=30m -failfast
+    go test -race -v -p=1 ./server/... -tags=skip_store_tests,skip_js_tests,skip_mqtt_tests,skip_msgtrace_tests -count=1 -vet=off -timeout=30m -failfast
 
 elif [ "$1" = "non_srv_pkg_tests" ]; then
 
diff --git a/server/events_test.go b/server/events_test.go
index f27fe86b..0d52ca20 100644
--- a/server/events_test.go
+++ b/server/events_test.go
@@ -103,14 +103,14 @@ func runTrustedCluster(t *testing.T) (*Server, *Options, *Server, *Options, nkey
 	mr.Store(apub, jwt)
 
 	optsA := DefaultOptions()
-	optsA.Cluster.Name = "TEST_CLUSTER_22"
+	optsA.Cluster.Name = "TEST CLUSTER 22"
 	optsA.Cluster.Host = "127.0.0.1"
 	optsA.TrustedKeys = []string{pub}
 	optsA.AccountResolver = mr
 	optsA.SystemAccount = apub
 	optsA.ServerName = "A_SRV"
 	// Add in dummy gateway
-	optsA.Gateway.Name = "TEST_CLUSTER_22"
+	optsA.Gateway.Name = "TEST CLUSTER 22"
 	optsA.Gateway.Host = "127.0.0.1"
 	optsA.Gateway.Port = -1
 	optsA.gatewaysSolicitDelay = 30 * time.Second
@@ -1876,7 +1876,7 @@ func TestServerEventsStatsZ(t *testing.T) {
 	if m.Server.ID != sa.ID() {
 		t.Fatalf("Did not match IDs")
 	}
-	if m.Server.Cluster != "TEST_CLUSTER_22" {
+	if m.Server.Cluster != "TEST CLUSTER 22" {
 		t.Fatalf("Did not match cluster name")
 	}
 	if m.Server.Version != VERSION {
@@ -2978,11 +2978,11 @@ func TestServerEventsPingMonitorz(t *testing.T) {
 			[]string{"now", "routes"}},
 		{"ROUTEZ", json.RawMessage(`{"name":""}`), &Routez{},
 			[]string{"now", "routes"}},
-		{"ROUTEZ", json.RawMessage(`{"cluster":"TEST_CLUSTER_22"}`), &Routez{},
+		{"ROUTEZ", json.RawMessage(`{"cluster":"TEST CLUSTER 22"}`), &Routez{},
 			[]string{"now", "routes"}},
 		{"ROUTEZ", json.RawMessage(`{"cluster":"CLUSTER"}`), &Routez{},
 			[]string{"now", "routes"}},
-		{"ROUTEZ", json.RawMessage(`{"cluster":"TEST_CLUSTER_22", "subscriptions":true}`), &Routez{},
+		{"ROUTEZ", json.RawMessage(`{"cluster":"TEST CLUSTER 22", "subscriptions":true}`), &Routez{},
 			[]string{"now", "routes"}},
 
 		{"JSZ", nil, &JSzOptions{}, []string{"now", "disabled"}},
@@ -3083,8 +3083,8 @@ func TestGatewayNameClientInfo(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Could not parse INFO json: %v\n", err)
 	}
-	if info.Cluster != "TEST_CLUSTER_22" {
-		t.Fatalf("Expected a cluster name of 'TEST_CLUSTER_22', got %q", info.Cluster)
+	if info.Cluster != "TEST CLUSTER 22" {
+		t.Fatalf("Expected a cluster name of 'TEST CLUSTER 22', got %q", info.Cluster)
 	}
 }
 
diff --git a/server/jetstream_cluster_2_test.go b/server/jetstream_cluster_2_test.go
index 0707f5e2..c551155a 100644
--- a/server/jetstream_cluster_2_test.go
+++ b/server/jetstream_cluster_2_test.go
@@ -7322,93 +7322,7 @@ func TestJetStreamClusterCompressedStreamMessages(t *testing.T) {
 	}
 }
 
-// https://github.com/nats-io/nats-server/issues/5612
-func TestJetStreamClusterWorkQueueLosingMessagesOnConsumerDelete(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3F", 3)
-	defer c.shutdown()
-
-	s := c.randomServer()
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:      "TEST",
-		Subjects:  []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"},
-		Retention: nats.WorkQueuePolicy,
-		Replicas:  3,
-	})
-	require_NoError(t, err)
-
-	msg := []byte("test alskdjalksdjalskdjaksdjlaksjdlkajsdlakjsdlakjsdlakjdlakjsdlaksjdlj")
-	for _, subj := range []string{"2", "5", "7", "9"} {
-		for i := 0; i < 10; i++ {
-			js.Publish(subj, msg)
-		}
-	}
-
-	cfg := &nats.ConsumerConfig{
-		Name:           "test",
-		FilterSubjects: []string{"6", "7", "8", "9", "10"},
-		DeliverSubject: "bob",
-		AckPolicy:      nats.AckExplicitPolicy,
-		AckWait:        time.Minute,
-		MaxAckPending:  1,
-	}
-
-	_, err = nc.SubscribeSync("bob")
-	require_NoError(t, err)
-
-	for i := 0; i < 5; i++ {
-		_, err = js.AddConsumer("TEST", cfg)
-		require_NoError(t, err)
-		time.Sleep(time.Second)
-		js.DeleteConsumer("TEST", "test")
-	}
-
-	si, err := js.StreamInfo("TEST")
-	require_NoError(t, err)
-	require_Equal(t, si.State.Msgs, 40)
-}
-
-func TestJetStreamClusterR1ConsumerAdvisory(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3F", 3)
-	defer c.shutdown()
-
-	s := c.randomServer()
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:      "TEST",
-		Subjects:  []string{"foo.*"},
-		Retention: nats.LimitsPolicy,
-		Replicas:  3,
-	})
-	require_NoError(t, err)
-
-	sub, err := nc.SubscribeSync("$JS.EVENT.ADVISORY.CONSUMER.CREATED.>")
-	require_NoError(t, err)
-
-	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
-		Durable:   "c1",
-		AckPolicy: nats.AckExplicitPolicy,
-		Replicas:  3,
-	})
-	require_NoError(t, err)
-
-	checkSubsPending(t, sub, 1)
-
-	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
-		Durable:   "c2",
-		AckPolicy: nats.AckExplicitPolicy,
-		Replicas:  1,
-	})
-	require_NoError(t, err)
-
-	checkSubsPending(t, sub, 2)
-}
-
 //
-// DO NOT ADD NEW TESTS IN THIS FILE  (unless to balance test times)
+// DO NOT ADD NEW TESTS IN THIS FILE
 // Add at the end of jetstream_cluster_<n>_test.go, with <n> being the highest value.
 //
diff --git a/server/jetstream_cluster_4_test.go b/server/jetstream_cluster_4_test.go
index 6add85e4..8407187e 100644
--- a/server/jetstream_cluster_4_test.go
+++ b/server/jetstream_cluster_4_test.go
@@ -24,7 +24,6 @@ import (
 	"math/rand"
 	"os"
 	"path/filepath"
-	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -2330,119 +2329,3 @@ func TestJetStreamClusterAckFloorBetweenLeaderAndFollowers(t *testing.T) {
 		}
 	}
 }
-
-// https://github.com/nats-io/nats-server/pull/5600
-func TestJetStreamClusterConsumerLeak(t *testing.T) {
-	N := 2000 // runs in under 10s, but significant enough to see the difference.
-	NConcurrent := 100
-
-	clusterConf := `
-	listen: 127.0.0.1:-1
-
-	server_name: %s
-	jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'}
-
-	leafnodes {
-		listen: 127.0.0.1:-1
-	}
-
-	cluster {
-		name: %s
-		listen: 127.0.0.1:%d
-		routes = [%s]
-	}
-
-	accounts {
-		ONE { users = [ { user: "one", pass: "p" } ]; jetstream: enabled }
-		$SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] }
-	}
-`
-
-	cl := createJetStreamClusterWithTemplate(t, clusterConf, "Leak-test", 3)
-	defer cl.shutdown()
-	cl.waitOnLeader()
-
-	s := cl.randomNonLeader()
-
-	// Create the test stream.
-	streamName := "LEAK_TEST_STREAM"
-	nc, js := jsClientConnect(t, s, nats.UserInfo("one", "p"))
-	defer nc.Close()
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:      streamName,
-		Subjects:  []string{"$SOMETHING.>"},
-		Storage:   nats.FileStorage,
-		Retention: nats.InterestPolicy,
-		Replicas:  3,
-	})
-	if err != nil {
-		t.Fatalf("Error creating stream: %v", err)
-	}
-
-	concurrent := make(chan struct{}, NConcurrent)
-	for i := 0; i < NConcurrent; i++ {
-		concurrent <- struct{}{}
-	}
-	errors := make(chan error, N)
-
-	wg := sync.WaitGroup{}
-	wg.Add(N)
-
-	// Gather the stats for comparison.
-	before := &runtime.MemStats{}
-	runtime.GC()
-	runtime.ReadMemStats(before)
-
-	for i := 0; i < N; {
-		// wait for a slot to open up
-		<-concurrent
-		i++
-		go func() {
-			defer func() {
-				concurrent <- struct{}{}
-				wg.Done()
-			}()
-
-			nc, js := jsClientConnect(t, s, nats.UserInfo("one", "p"))
-			defer nc.Close()
-
-			consumerName := "sessid_" + nuid.Next()
-			_, err := js.AddConsumer(streamName, &nats.ConsumerConfig{
-				DeliverSubject: "inbox",
-				Durable:        consumerName,
-				AckPolicy:      nats.AckExplicitPolicy,
-				DeliverPolicy:  nats.DeliverNewPolicy,
-				FilterSubject:  "$SOMETHING.ELSE.subject",
-				AckWait:        30 * time.Second,
-				MaxAckPending:  1024,
-			})
-			if err != nil {
-				errors <- fmt.Errorf("Error on JetStream consumer creation: %v", err)
-				return
-			}
-
-			err = js.DeleteConsumer(streamName, consumerName)
-			if err != nil {
-				errors <- fmt.Errorf("Error on JetStream consumer deletion: %v", err)
-			}
-		}()
-	}
-
-	wg.Wait()
-	if len(errors) > 0 {
-		for err := range errors {
-			t.Fatalf("%v", err)
-		}
-	}
-
-	after := &runtime.MemStats{}
-	runtime.GC()
-	runtime.ReadMemStats(after)
-
-	// Before https://github.com/nats-io/nats-server/pull/5600 this test was
-	// adding 180Mb+ to HeapInuse. Now it's under 40Mb (ran locally on a Mac)
-	limit := before.HeapInuse + 100*1024*1024 // 100MB
-	if after.HeapInuse > before.HeapInuse+limit {
-		t.Fatalf("Extra memory usage too high: %v", after.HeapInuse-before.HeapInuse)
-	}
-}
diff --git a/server/jetstream_test.go b/server/jetstream_test.go
index cfe85f92..d153255a 100644
--- a/server/jetstream_test.go
+++ b/server/jetstream_test.go
@@ -11577,7 +11577,7 @@ func TestJetStreamMirrorBasics(t *testing.T) {
 		Name:    "MBAD",
 		Storage: FileStorage,
 		Mirror:  &StreamSource{Name: "S1", SubjectTransforms: []SubjectTransformConfig{{Source: "*", Destination: "{{wildcard(2)}}"}}},
-	}, ApiErrors[JSMirrorInvalidTransformDestination].ErrCode)
+	}, ApiErrors[JSStreamCreateErrF].ErrCode)
 
 	createStreamServerStreamConfig(&StreamConfig{
 		Name:    "MBAD",
@@ -23760,111 +23760,6 @@ func TestJetStreamBadSubjectMappingStream(t *testing.T) {
 			},
 		},
 	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: source transform: invalid mapping destination: too many arguments passed to the function in {{wildcard(1)}}{{split(3,1)}}")))
 
-	_, err = js.UpdateStream(&nats.StreamConfig{
-		Name: "test",
-		Sources: []*nats.StreamSource{
-			{
-				Name: "mapping",
-				SubjectTransforms: []nats.SubjectTransformConfig{
-					{
-						Source:      "events.>.*",
-						Destination: "events.{{split(1,1)}}",
-					},
-				},
-			},
-		},
-	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: source transform source: invalid subject events.>.*")))
-
-	_, err = js.UpdateStream(&nats.StreamConfig{
-		Name: "test",
-		Mirror: &nats.StreamSource{
-			Name: "mapping",
-			SubjectTransforms: []nats.SubjectTransformConfig{
-				{
-					Source:      "events.*",
-					Destination: "events.{{split(3,1)}}",
-				},
-			},
-		},
-	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: mirror transform: invalid mapping destination: wildcard index out of range in {{split(3,1)}}: [3]")))
-
-	_, err = js.UpdateStream(&nats.StreamConfig{
-		Name: "test",
-		Mirror: &nats.StreamSource{
-			Name: "mapping",
-			SubjectTransforms: []nats.SubjectTransformConfig{
-				{
-					Source:      "events.>.*",
-					Destination: "events.{{split(1,1)}}",
-				},
-			},
-		},
-	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: mirror transform source: invalid subject events.>.*")))
-
-	_, err = js.UpdateStream(&nats.StreamConfig{
-		Name: "test",
-		SubjectTransform: &nats.SubjectTransformConfig{
-			Source:      "events.*",
-			Destination: "events.{{split(3,1)}}",
-		},
-	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: stream transform: invalid mapping destination: wildcard index out of range in {{split(3,1)}}: [3]")))
-
-	_, err = js.UpdateStream(&nats.StreamConfig{
-		Name: "test",
-		SubjectTransform: &nats.SubjectTransformConfig{
-			Source:      "events.>.*",
-			Destination: "events.{{split(1,1)}}",
-		},
-	})
-	require_Error(t, err, NewJSStreamUpdateError(errors.New("nats: stream transform source: invalid subject events.>.*")))
-}
-
-func TestJetStreamConsumerInfoNumPending(t *testing.T) {
-	s := RunBasicJetStreamServer(t)
-	defer s.Shutdown()
-
-	// Client for API requests.
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:     "LIMITS",
-		Subjects: []string{"js.in.limits"},
-		MaxMsgs:  100,
-	})
-	require_NoError(t, err)
-
-	_, err = js.AddConsumer("LIMITS", &nats.ConsumerConfig{
-		Name:      "PULL",
-		AckPolicy: nats.AckExplicitPolicy,
-	})
-	require_NoError(t, err)
-
-	for i := 0; i < 1000; i++ {
-		js.Publish("js.in.limits", []byte("x"))
-	}
-
-	ci, err := js.ConsumerInfo("LIMITS", "PULL")
-	require_NoError(t, err)
-	require_Equal(t, ci.NumPending, 100)
-
-	// Now restart the server.
-	sd := s.JetStreamConfig().StoreDir
-	s.Shutdown()
-	// Restart.
-	s = RunJetStreamServerOnPort(-1, sd)
-	defer s.Shutdown()
-
-	nc, js = jsClientConnect(t, s)
-	defer nc.Close()
-
-	ci, err = js.ConsumerInfo("LIMITS", "PULL")
-	require_NoError(t, err)
-	require_Equal(t, ci.NumPending, 100)
+	require_Error(t, err, NewJSStreamUpdateError(errors.New("unable to get subject transform for source: invalid mapping destination: too many arguments passed to the function in {{wildcard(1)}}{{split(3,1)}}")))
 }
diff --git a/server/monitor_test.go b/server/monitor_test.go
index 60faf361..949fdb8e 100644
--- a/server/monitor_test.go
+++ b/server/monitor_test.go
@@ -4298,9 +4298,6 @@ func TestMonitorJsz(t *testing.T) {
 			max_file_store: 10Mb
 			store_dir: '%s'
 			unique_tag: az
-			limits: {
-				max_ha_assets: 1000
-			}
 		}
 		cluster {
 			name: cluster_name
@@ -4380,9 +4377,6 @@ func TestMonitorJsz(t *testing.T) {
 			if info.Messages != 2 {
 				t.Fatalf("expected two message but got %d", info.Messages)
 			}
-			if info.Limits.MaxHAAssets != 1000 {
-				t.Fatalf("expected max_ha_assets limit to be 1000 got %v", info.Limits)
-			}
 		}
 	})
 	t.Run("accounts", func(t *testing.T) {
diff --git a/server/raft_test.go b/server/raft_test.go
index 692d3d51..beb15d63 100644
--- a/server/raft_test.go
+++ b/server/raft_test.go
@@ -184,21 +184,6 @@ func TestNRGRecoverFromFollowingNoLeader(t *testing.T) {
 	require_NotEqual(t, rg.leader().node().Term(), term)
 }
 
-func TestNRGInlineStepdown(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3S", 3)
-	defer c.shutdown()
-
-	rg := c.createMemRaftGroup("TEST", 3, newStateAdder)
-	rg.waitOnLeader()
-
-	// When StepDown() completes, we should not be the leader. Before,
-	// this would not be guaranteed as the stepdown could be processed
-	// some time later.
-	n := rg.leader().node().(*raft)
-	require_NoError(t, n.StepDown())
-	require_NotEqual(t, n.State(), Leader)
-}
-
 func TestNRGObserverMode(t *testing.T) {
 	c := createJetStreamClusterExplicit(t, "R3S", 3)
 	defer c.shutdown()
@@ -235,53 +220,6 @@ func TestNRGObserverMode(t *testing.T) {
 	}
 }
 
-func TestNRGAEFromOldLeader(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3S", 3)
-	defer c.shutdown()
-
-	nc, _ := jsClientConnect(t, c.leader(), nats.UserInfo("admin", "s3cr3t!"))
-	defer nc.Close()
-
-	rg := c.createMemRaftGroup("TEST", 3, newStateAdder)
-	rg.waitOnLeader()
-
-	// Listen out for catchup requests.
-	ch := make(chan *nats.Msg, 16)
-	_, err := nc.ChanSubscribe(fmt.Sprintf(raftCatchupReply, ">"), ch)
-	require_NoError(t, err)
-
-	// Start next term so that we can reuse term 1 in the next step.
-	leader := rg.leader().node().(*raft)
-	leader.StepDown()
-	time.Sleep(time.Millisecond * 100)
-	rg.waitOnLeader()
-	require_Equal(t, leader.Term(), 2)
-	leader = rg.leader().node().(*raft)
-
-	// Send an append entry with an outdated term. Beforehand, doing
-	// so would have caused a WAL reset and then would have triggered
-	// a Raft-level catchup.
-	ae := &appendEntry{
-		term:   1,
-		pindex: 0,
-		leader: leader.id,
-		reply:  nc.NewRespInbox(),
-	}
-	payload, err := ae.encode(nil)
-	require_NoError(t, err)
-	resp, err := nc.Request(leader.asubj, payload, time.Second)
-	require_NoError(t, err)
-
-	// Wait for the response, the server should have rejected it.
-	ar := leader.decodeAppendEntryResponse(resp.Data)
-	require_NotNil(t, ar)
-	require_Equal(t, ar.success, false)
-
-	// No catchup should happen at this point because no reset should
-	// have happened.
-	require_NoChanRead(t, ch, time.Second*2)
-}
-
 // TestNRGSimpleElection tests that a simple election succeeds. It is
 // simple because the group hasn't processed any entries and hasn't
 // suffered any interruptions of any kind, therefore there should be
@@ -357,28 +295,6 @@ func TestNRGSimpleElection(t *testing.T) {
 	}
 }
 
-func TestNRGSwitchStateClearsQueues(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3S", 3)
-	defer c.shutdown()
-
-	rg := c.createMemRaftGroup("TEST", 3, newStateAdder)
-	rg.waitOnLeader()
-
-	sa := rg.leader().(*stateAdder)
-	n := sa.node().(*raft)
-
-	for i := 0; i < 10_000; i++ {
-		sa.proposeDelta(1)
-	}
-
-	n.Lock()
-	defer n.Unlock()
-
-	n.switchState(Follower)
-	require_Equal(t, n.prop.len(), 0)
-	require_Equal(t, n.resp.len(), 0)
-}
-
 func TestNRGStepDownOnSameTermDoesntClearVote(t *testing.T) {
 	c := createJetStreamClusterExplicit(t, "R3S", 3)
 	defer c.shutdown()
@@ -514,7 +430,7 @@ func TestNRGInvalidTAVDoesntPanic(t *testing.T) {
 	c.waitOnAllCurrent()
 }
 
-func TestNRGAssumeHighTermAfterCandidateIsolation(t *testing.T) {
+func TestNRGCandidateStepsDownAfterAE(t *testing.T) {
 	c := createJetStreamClusterExplicit(t, "R3S", 3)
 	defer c.shutdown()
 	c.waitOnLeader()
@@ -525,38 +441,32 @@ func TestNRGAssumeHighTermAfterCandidateIsolation(t *testing.T) {
 	rg := c.createRaftGroup("TEST", 3, newStateAdder)
 	rg.waitOnLeader()
 
-	// Bump the term up on one of the follower nodes by a considerable
+	// Pick a random follower node. Bump the term up by a considerable
 	// amount and force it into the candidate state. This is what happens
 	// after a period of time in isolation.
-	follower := rg.nonLeader().node().(*raft)
-	follower.Lock()
-	follower.term += 100
-	follower.switchState(Candidate)
-	follower.Unlock()
-
-	follower.requestVote()
-	time.Sleep(time.Millisecond * 100)
-
-	// The candidate will shortly send a vote request. When that happens,
-	// the rest of the nodes in the cluster should move up to that term,
-	// even though they will not grant the vote.
-	nterm := follower.term
-	for _, n := range rg {
-		require_Equal(t, n.node().Term(), nterm)
-	}
+	n := rg.nonLeader().node().(*raft)
+	n.Lock()
+	n.term += 100
+	n.switchState(Candidate)
+	n.Unlock()
 
-	// Have the leader send out a proposal, which will force the candidate
-	// back into follower state.
-	rg.waitOnLeader()
+	// Have the leader push through something on the current term just
+	// for good measure, although the heartbeats probably work too.
 	rg.leader().(*stateAdder).proposeDelta(1)
-	rg.waitOnTotal(t, 1)
 
-	// The candidate should have switched to a follower on a term equal to
-	// or newer than the candidate had.
-	for _, n := range rg {
-		require_NotEqual(t, n.node().State(), Candidate)
-		require_True(t, n.node().Term() >= nterm)
-	}
+	// Wait for the leader to receive the next append entry from the
+	// current leader. What should happen is that the node steps down
+	// and starts following the leader, as nothing in the log of the
+	// follower is newer than the term of the leader.
+	checkFor(t, time.Second, 50*time.Millisecond, func() error {
+		if n.State() == Candidate {
+			return fmt.Errorf("shouldn't still be candidate state")
+		}
+		if nterm, lterm := n.Term(), rg.leader().node().Term(); nterm != lterm {
+			return fmt.Errorf("follower term %d should match leader term %d", nterm, lterm)
+		}
+		return nil
+	})
 }
 
 // Test to make sure this does not cause us to truncate our wal or enter catchup state.
@@ -678,117 +588,3 @@ func TestNRGLeavesObserverAfterPause(t *testing.T) {
 	n.ResumeApply()
 	checkState(false, false)
 }
-
-func TestNRGCandidateDoesntRevertTermAfterOldAE(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3S", 3)
-	defer c.shutdown()
-
-	rg := c.createMemRaftGroup("TEST", 3, newStateAdder)
-	rg.waitOnLeader()
-
-	// Bump the term up a few times.
-	for i := 0; i < 3; i++ {
-		rg.leader().node().StepDown()
-		time.Sleep(time.Millisecond * 50) // Needed because stepdowns not synchronous
-		rg.waitOnLeader()
-	}
-
-	leader := rg.leader().node().(*raft)
-	follower := rg.nonLeader().node().(*raft)
-
-	// Sanity check that we are where we expect to be.
-	require_Equal(t, leader.term, 4)
-	require_Equal(t, follower.term, 4)
-
-	// At this point the active term is 4 and pterm is 4, force the
-	// term up to 9. This won't bump the pterm.
-	rg.lockAll()
-	for _, n := range rg {
-		n.node().(*raft).term += 5
-	}
-	rg.unlockAll()
-
-	// Build an AE that has a term newer than the pterm but older than
-	// the term. Give it to the follower in candidate state.
-	ae := newAppendEntry(leader.id, 6, leader.commit, leader.pterm, leader.pindex, nil)
-	follower.switchToCandidate()
-	follower.processAppendEntry(ae, nil)
-
-	// The candidate must not have reverted back to term 6.
-	require_NotEqual(t, follower.term, 6)
-}
-
-func TestNRGTermDoesntRollBackToPtermOnCatchup(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "R3S", 3)
-	defer c.shutdown()
-
-	nc, _ := jsClientConnect(t, c.leader(), nats.UserInfo("admin", "s3cr3t!"))
-	defer nc.Close()
-
-	rg := c.createMemRaftGroup("TEST", 3, newStateAdder)
-	rg.waitOnLeader()
-
-	// Propose some entries so that we have entries in the log that have pterm 1.
-	lsm := rg.leader().(*stateAdder)
-	for i := 0; i < 5; i++ {
-		lsm.proposeDelta(1)
-		rg.waitOnTotal(t, int64(i)+1)
-	}
-
-	// Check that everyone is where they are supposed to be.
-	rg.lockAll()
-	for _, n := range rg {
-		rn := n.node().(*raft)
-		require_Equal(t, rn.term, 1)
-		require_Equal(t, rn.pterm, 1)
-		require_Equal(t, rn.pindex, 6)
-	}
-	rg.unlockAll()
-
-	// Force a stepdown so that we move up to term 2.
-	rg.leader().node().(*raft).switchToFollower(noLeader)
-	rg.waitOnLeader()
-	leader := rg.leader().node().(*raft)
-
-	// Now make sure everyone has moved up to term 2. Additionally we're
-	// going to prune back the follower logs to term 1 as this is what will
-	// create the right conditions for the catchup.
-	rg.lockAll()
-	for _, n := range rg {
-		rn := n.node().(*raft)
-		require_Equal(t, rn.term, 2)
-
-		if !rn.Leader() {
-			rn.truncateWAL(1, 6) // This will overwrite rn.term, so...
-			rn.term = 2          // ... we'll set it back manually.
-			require_Equal(t, rn.pterm, 1)
-			require_Equal(t, rn.pindex, 6)
-		}
-	}
-	rg.unlockAll()
-
-	arInbox := nc.NewRespInbox()
-	arCh := make(chan *nats.Msg, 2)
-	_, err := nc.ChanSubscribe(arInbox, arCh)
-	require_NoError(t, err)
-
-	// In order to trip this condition, we need to send an append entry that
-	// will trick the followers into running a catchup. In the process they
-	// were setting the term back to pterm which is incorrect.
-	ae := newAppendEntry(leader.id, leader.term, leader.commit, leader.pterm, leader.pindex, nil)
-	b, err := ae.encode(nil)
-	require_NoError(t, err)
-	require_NoError(t, nc.PublishMsg(&nats.Msg{
-		Subject: fmt.Sprintf(raftAppendSubj, "TEST"),
-		Reply:   arInbox,
-		Data:    b,
-	}))
-
-	// Wait for both followers to respond to the append entry and then verify
-	// that none of the nodes should have reverted back to term 1.
-	require_ChanRead(t, arCh, time.Second*5) // First follower
-	require_ChanRead(t, arCh, time.Second*5) // Second follower
-	for _, n := range rg {
-		require_NotEqual(t, n.node().Term(), 1)
-	}
-}
diff --git a/server/routes_test.go b/server/routes_test.go
index 639143cc..a65b3f78 100644
--- a/server/routes_test.go
+++ b/server/routes_test.go
@@ -738,10 +738,15 @@ func TestClientConnectToRoutePort(t *testing.T) {
 }
 
 type checkDuplicateRouteLogger struct {
-	DummyLogger
+	sync.Mutex
 	gotDuplicate bool
 }
 
+func (l *checkDuplicateRouteLogger) Noticef(format string, v ...any) {}
+func (l *checkDuplicateRouteLogger) Errorf(format string, v ...any)  {}
+func (l *checkDuplicateRouteLogger) Warnf(format string, v ...any)   {}
+func (l *checkDuplicateRouteLogger) Fatalf(format string, v ...any)  {}
+func (l *checkDuplicateRouteLogger) Tracef(format string, v ...any)  {}
 func (l *checkDuplicateRouteLogger) Debugf(format string, v ...any) {
 	l.Lock()
 	defer l.Unlock()
@@ -3352,8 +3357,7 @@ func TestRoutePoolAndPerAccountWithOlderServer(t *testing.T) {
 
 type testDuplicateRouteLogger struct {
 	DummyLogger
-	ch    chan struct{}
-	count int
+	ch chan struct{}
 }
 
 func (l *testDuplicateRouteLogger) Noticef(format string, args ...any) {
@@ -3365,9 +3369,6 @@ func (l *testDuplicateRouteLogger) Noticef(format string, args ...any) {
 	case l.ch <- struct{}{}:
 	default:
 	}
-	l.Mutex.Lock()
-	l.count++
-	l.Mutex.Unlock()
 }
 
 // This test will make sure that a server with pooling does not
@@ -4350,176 +4351,3 @@ func TestRouteNoRaceOnClusterNameNegotiation(t *testing.T) {
 		s1.Shutdown()
 	}
 }
-
-func TestRouteImplicitNotTooManyDuplicates(t *testing.T) {
-	for _, test := range []struct {
-		name        string
-		pooling     bool
-		compression bool
-	}{
-		{"no pooling-no compression", false, false},
-		{"no pooling-compression", false, true},
-		{"pooling-no compression", true, false},
-		{"pooling-compression", true, true},
-	} {
-		t.Run(test.name, func(t *testing.T) {
-			o := DefaultOptions()
-			o.ServerName = "SEED"
-			if !test.pooling {
-				o.Cluster.PoolSize = -1
-			}
-			if !test.compression {
-				o.Cluster.Compression.Mode = CompressionOff
-			}
-			seed := RunServer(o)
-			defer seed.Shutdown()
-
-			dl := &testDuplicateRouteLogger{}
-
-			servers := make([]*Server, 0, 10)
-			for i := 0; i < cap(servers); i++ {
-				io := DefaultOptions()
-				io.ServerName = fmt.Sprintf("IMPLICIT_%d", i+1)
-				io.NoLog = false
-				io.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o.Cluster.Port))
-				if !test.pooling {
-					io.Cluster.PoolSize = -1
-				}
-				if !test.compression {
-					io.Cluster.Compression.Mode = CompressionOff
-				}
-				is, err := NewServer(io)
-				require_NoError(t, err)
-				// Will do defer of shutdown later.
-				is.SetLogger(dl, true, false)
-				is.Start()
-				servers = append(servers, is)
-			}
-
-			allServers := make([]*Server, 0, len(servers)+1)
-			allServers = append(allServers, seed)
-			allServers = append(allServers, servers...)
-
-			// Let's make sure that we wait for each server to be ready.
-			for _, s := range allServers {
-				if !s.ReadyForConnections(2 * time.Second) {
-					t.Fatalf("Server %q is not ready for connections", s)
-				}
-			}
-
-			// Do the defer of shutdown of all servers this way instead of individual
-			// defers when starting them. It takes less time for the servers to shutdown
-			// this way.
-			defer func() {
-				for _, s := range allServers {
-					s.Shutdown()
-				}
-			}()
-			checkClusterFormed(t, allServers...)
-
-			dl.Mutex.Lock()
-			count := dl.count
-			dl.Mutex.Unlock()
-			// Getting duplicates should not be considered fatal, it is an optimization
-			// to reduce the occurrences of those. But to make sure we don't have a
-			// regression, we will fail the test if we get say more than 20 or so (
-			// without the code change, we would get more than 500 of duplicates).
-			if count > 20 {
-				t.Fatalf("Got more duplicates than anticipated: %v", count)
-			}
-		})
-	}
-}
-
-func TestRouteImplicitJoinsSeparateGroups(t *testing.T) {
-	// The test TestRouteImplicitNotTooManyDuplicates makes sure that we do
-	// not have too many duplicate routes cases when processing implicit routes.
-	// This test is to ensure that the code changes to reduce the number
-	// of duplicate routes does not prevent the formation of the cluster
-	// with the given setup (which is admittedly not good since a disconnect
-	// between some routes would not result in a reconnect leading to a full mesh).
-	// Still, original code was able to create the original full mesh, so we want
-	// to make sure that this is still possible.
-	for _, test := range []struct {
-		name        string
-		pooling     bool
-		compression bool
-	}{
-		{"no pooling-no compression", false, false},
-		{"no pooling-compression", false, true},
-		{"pooling-no compression", true, false},
-		{"pooling-compression", true, true},
-	} {
-		t.Run(test.name, func(t *testing.T) {
-			setOpts := func(o *Options) {
-				if !test.pooling {
-					o.Cluster.PoolSize = -1
-				}
-				if !test.compression {
-					o.Cluster.Compression.Mode = CompressionOff
-				}
-			}
-
-			// Create a cluster s1/s2/s3
-			o1 := DefaultOptions()
-			o1.ServerName = "S1"
-			setOpts(o1)
-			s1 := RunServer(o1)
-			defer s1.Shutdown()
-
-			o2 := DefaultOptions()
-			o2.ServerName = "S2"
-			setOpts(o2)
-			o2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o1.Cluster.Port))
-			s2 := RunServer(o2)
-			defer s2.Shutdown()
-
-			tmpl := `
-				server_name: "S3"
-				listen: "127.0.0.1:-1"
-				cluster {
-					name: "abc"
-					listen: "127.0.0.1:-1"
-					%s
-					%s
-					routes: ["nats://127.0.0.1:%d"%s]
-				}
-			`
-			var poolCfg string
-			var compressionCfg string
-			if !test.pooling {
-				poolCfg = "pool_size: -1"
-			}
-			if !test.compression {
-				compressionCfg = "compression: off"
-			}
-			conf := createConfFile(t, []byte(fmt.Sprintf(tmpl, poolCfg, compressionCfg, o1.Cluster.Port, _EMPTY_)))
-			s3, _ := RunServerWithConfig(conf)
-			defer s3.Shutdown()
-
-			checkClusterFormed(t, s1, s2, s3)
-
-			// Now s4 and s5 connected to each other, but not linked to s1/s2/s3
-			o4 := DefaultOptions()
-			o4.ServerName = "S4"
-			setOpts(o4)
-			s4 := RunServer(o4)
-			defer s4.Shutdown()
-
-			o5 := DefaultOptions()
-			o5.ServerName = "S5"
-			setOpts(o5)
-			o5.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o4.Cluster.Port))
-			s5 := RunServer(o5)
-			defer s5.Shutdown()
-
-			checkClusterFormed(t, s4, s5)
-
-			// Now add a route from s3 to s4 and make sure that we have a full mesh.
-			routeToS4 := fmt.Sprintf(`, "nats://127.0.0.1:%d"`, o4.Cluster.Port)
-			reloadUpdateConfig(t, s3, conf, fmt.Sprintf(tmpl, poolCfg, compressionCfg, o1.Cluster.Port, routeToS4))
-
-			checkClusterFormed(t, s1, s2, s3, s4, s5)
-		})
-	}
-}
diff --git a/server/server_test.go b/server/server_test.go
index 45ea9f93..483fb7be 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -143,17 +143,6 @@ func TestVersionMatchesTag(t *testing.T) {
 	if VERSION != tag[1:] {
 		t.Fatalf("Version (%s) does not match tag (%s)", VERSION, tag[1:])
 	}
-	// Check that the version dynamically set via ldflags matches the version
-	// from the server previous to releasing.
-	if serverVersion == _EMPTY_ {
-		t.Fatal("Version missing in ldflags")
-	}
-	// Unlike VERSION constant, serverVersion is prefixed with a 'v'
-	// since it should be the same as the git tag.
-	expected := "v" + VERSION
-	if serverVersion != _EMPTY_ && expected != serverVersion {
-		t.Fatalf("Version (%s) does not match ldflags version (%s)", expected, serverVersion)
-	}
 }
 
 func TestStartProfiler(t *testing.T) {
@@ -2150,53 +2139,3 @@ func TestServerConfigLastLineComments(t *testing.T) {
 	require_NoError(t, err)
 	defer nc.Close()
 }
-
-func TestServerClusterAndGatewayNameNoSpace(t *testing.T) {
-	conf := createConfFile(t, []byte(`
-		port: -1
-		server_name: "my server"
-	`))
-	_, err := ProcessConfigFile(conf)
-	require_Error(t, err, ErrServerNameHasSpaces)
-
-	o := DefaultOptions()
-	o.ServerName = "my server"
-	_, err = NewServer(o)
-	require_Error(t, err, ErrServerNameHasSpaces)
-
-	conf = createConfFile(t, []byte(`
-		port: -1
-		server_name: "myserver"
-		cluster {
-			port: -1
-			name: "my cluster"
-		}
-	`))
-	_, err = ProcessConfigFile(conf)
-	require_Error(t, err, ErrClusterNameHasSpaces)
-
-	o = DefaultOptions()
-	o.Cluster.Name = "my cluster"
-	o.Cluster.Port = -1
-	_, err = NewServer(o)
-	require_Error(t, err, ErrClusterNameHasSpaces)
-
-	conf = createConfFile(t, []byte(`
-		port: -1
-		server_name: "myserver"
-		gateway {
-			port: -1
-			name: "my gateway"
-		}
-	`))
-	_, err = ProcessConfigFile(conf)
-	require_Error(t, err, ErrGatewayNameHasSpaces)
-
-	o = DefaultOptions()
-	o.Cluster.Name = _EMPTY_
-	o.Cluster.Port = 0
-	o.Gateway.Name = "my gateway"
-	o.Gateway.Port = -1
-	_, err = NewServer(o)
-	require_Error(t, err, ErrGatewayNameHasSpaces)
-}
diff --git a/server/stree/stree_test.go b/server/stree/stree_test.go
index 7177cd6d..7ce59e28 100644
--- a/server/stree/stree_test.go
+++ b/server/stree/stree_test.go
@@ -764,14 +764,3 @@ func TestSubjectTreeMatchNoCallbackDupe(t *testing.T) {
 		})
 	}
 }
-
-func TestSubjectTreeNilNoPanic(t *testing.T) {
-	var st *SubjectTree[int]
-	st.Match([]byte("foo"), func(_ []byte, _ *int) {})
-	_, found := st.Find([]byte("foo"))
-	require_False(t, found)
-	_, found = st.Delete([]byte("foo"))
-	require_False(t, found)
-	_, found = st.Insert([]byte("foo"), 22)
-	require_False(t, found)
-}
diff --git a/server/sublist_test.go b/server/sublist_test.go
index e7d78b7b..966401b5 100644
--- a/server/sublist_test.go
+++ b/server/sublist_test.go
@@ -679,24 +679,24 @@ func TestSubjectIsLiteral(t *testing.T) {
 }
 
 func TestValidateDestinationSubject(t *testing.T) {
-	checkError(ValidateMapping("bar", "foo"), nil, t)
-	checkError(ValidateMapping("foo", "foo.bar"), nil, t)
-	checkError(ValidateMapping("*", "{{wildcard(1)}}"), nil, t)
-	checkError(ValidateMapping("foo.>", ">"), nil, t)
-	checkError(ValidateMapping("foo.*", "bar.{{wildcard(1)}}"), nil, t)
-	checkError(ValidateMapping("foo.>", "bar.>"), nil, t)
-	checkError(ValidateMapping("foo.*.>", "bar.{{wildcard(1)}}.>"), nil, t)
-	checkError(ValidateMapping("foo.*.bar", "bar.{{wildcard(1)}}.foo"), nil, t)
-	checkError(ValidateMapping("foo.bar.>", "foo.bar.foo.>"), nil, t)
-	checkError(ValidateMapping("*", "foo.{{wildcard(1)}}"), nil, t)
-	checkError(ValidateMapping("*", "foo.{{ wildcard(1) }}"), nil, t)
-	checkError(ValidateMapping("*", "foo.{{wildcard( 1 )}}"), nil, t)
-	checkError(ValidateMapping("*", "foo.{{partition(2,1)}}"), nil, t)
-	checkError(ValidateMapping("*.*", "foo.{{SplitFromLeft(2,1)}}"), nil, t)
-	checkError(ValidateMapping("*.*", "foo.{{SplitFromRight(2,1)}}"), nil, t)
-	checkError(ValidateMapping("*", "foo.{{unknown(1)}}"), ErrInvalidMappingDestination, t)
-	checkError(ValidateMapping("foo", "foo..}"), ErrInvalidMappingDestination, t)
-	checkError(ValidateMapping("foo", "foo. bar}"), ErrInvalidMappingDestinationSubject, t)
+	checkError(ValidateMappingDestination("foo"), nil, t)
+	checkError(ValidateMappingDestination("foo.bar"), nil, t)
+	checkError(ValidateMappingDestination("*"), nil, t)
+	checkError(ValidateMappingDestination(">"), nil, t)
+	checkError(ValidateMappingDestination("foo.*"), nil, t)
+	checkError(ValidateMappingDestination("foo.>"), nil, t)
+	checkError(ValidateMappingDestination("foo.*.>"), nil, t)
+	checkError(ValidateMappingDestination("foo.*.bar"), nil, t)
+	checkError(ValidateMappingDestination("foo.bar.>"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{wildcard(1)}}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{ wildcard(1) }}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{wildcard( 1 )}}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{partition(2,1)}}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{SplitFromLeft(2,1)}}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{SplitFromRight(2,1)}}"), nil, t)
+	checkError(ValidateMappingDestination("foo.{{unknown(1)}}"), ErrInvalidMappingDestination, t)
+	checkError(ValidateMappingDestination("foo..}"), ErrInvalidMappingDestination, t)
+	checkError(ValidateMappingDestination("foo. bar}"), ErrInvalidMappingDestinationSubject, t)
 
 }
 
diff --git a/test/leafnode_test.go b/test/leafnode_test.go
index fb3dff89..b1bfb132 100644
--- a/test/leafnode_test.go
+++ b/test/leafnode_test.go
@@ -4426,27 +4426,3 @@ func TestLeafnodeHeaders(t *testing.T) {
 		t.Fatalf("leaf msg header is empty")
 	}
 }
-
-func TestLeafNodeClusterNameWithSpacesRejected(t *testing.T) {
-	s, opts := runLeafServer()
-	defer s.Shutdown()
-
-	lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port)
-	defer lc.Close()
-
-	checkInfoMsg(t, lc)
-	sendProto(t, lc, "CONNECT {\"cluster\":\"my cluster\"}\r\n")
-	expect := expectCommand(t, lc)
-	expect(errRe)
-	expectDisconnect(t, lc)
-
-	lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port)
-	defer lc.Close()
-	leafSend, leafExpect := setupLeaf(t, lc, 1)
-	// The accept side does expect an INFO from an handshake,
-	// so it will "ignore" the first one.
-	leafSend("INFO {\"server\":\"server\"}\r\n")
-	leafSend("INFO {\"cluster\":\"my cluster\"}\r\n")
-	leafExpect(errRe)
-	expectDisconnect(t, lc)
-}