Repository: nats-io/nats-server
Pull request #2431 (2021-08-11 15:46:50)

fixed unit test to require fc export as well
Signed-off-by: Matthias Hanel <mh@synadia.com>

Realized that FC needed to be exported as well...


Patch:
diff --git a/go.mod b/go.mod
index 26c2db4f..7dd4f91b 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,7 @@ require (
 	github.com/klauspost/compress v1.11.12
 	github.com/minio/highwayhash v1.0.1
 	github.com/nats-io/jwt/v2 v2.0.3
-	github.com/nats-io/nats.go v1.11.1-0.20210810010129-d1955c8653ca
+	github.com/nats-io/nats.go v1.11.1-0.20210803204434-91bdffe39f41
 	github.com/nats-io/nkeys v0.3.0
 	github.com/nats-io/nuid v1.0.1
 	golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
diff --git a/go.sum b/go.sum
index 6bd7fe72..46e4fff1 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,6 @@ github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30 h1:9GqilBhZaR3x
 github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nats.go v1.11.1-0.20210803204434-91bdffe39f41 h1:GUUkiOgD00OMr4foruBN6YG1be3lFnHl0LJIoEs8cQg=
 github.com/nats-io/nats.go v1.11.1-0.20210803204434-91bdffe39f41/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
-github.com/nats-io/nats.go v1.11.1-0.20210810010129-d1955c8653ca h1:9MdvV5kneekw/B/TebU4Om19T3eOUBRB3yP1c82yKSk=
-github.com/nats-io/nats.go v1.11.1-0.20210810010129-d1955c8653ca/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
diff --git a/server/consumer.go b/server/consumer.go
index e9ad5543..f2786ad9 100644
--- a/server/consumer.go
+++ b/server/consumer.go
@@ -276,69 +276,69 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 	}
 
 	if config == nil {
-		return nil, NewJSConsumerConfigRequiredError()
+		return nil, ApiErrors[JSConsumerConfigRequiredErr]
 	}
 
 	if len(config.Description) > JSMaxDescriptionLen {
-		return nil, NewJSConsumerDescriptionTooLongError(JSMaxDescriptionLen)
+		return nil, ApiErrors[JSConsumerDescriptionTooLongErrF].NewT("{max}", JSMaxDescriptionLen)
 	}
 
 	var err error
 	// For now expect a literal subject if its not empty. Empty means work queue mode (pull mode).
 	if config.DeliverSubject != _EMPTY_ {
 		if !subjectIsLiteral(config.DeliverSubject) {
-			return nil, NewJSConsumerDeliverToWildcardsError()
+			return nil, ApiErrors[JSConsumerDeliverToWildcardsErr]
 		}
 		if mset.deliveryFormsCycle(config.DeliverSubject) {
-			return nil, NewJSConsumerDeliverCycleError()
+			return nil, ApiErrors[JSConsumerDeliverCycleErr]
 		}
 		if config.MaxWaiting != 0 {
-			return nil, NewJSConsumerPushMaxWaitingError()
+			return nil, ApiErrors[JSConsumerDeliverToWildcardsErr]
 		}
 		if config.MaxAckPending > 0 && config.AckPolicy == AckNone {
-			return nil, NewJSConsumerMaxPendingAckPolicyRequiredError()
+			return nil, ApiErrors[JSConsumerMaxPendingAckPolicyRequiredErr]
 		}
 		if config.Heartbeat > 0 && config.Heartbeat < 100*time.Millisecond {
-			return nil, NewJSConsumerSmallHeartbeatError()
+			return nil, ApiErrors[JSConsumerSmallHeartbeatErr]
 		}
 	} else {
 		// Pull mode / work queue mode require explicit ack.
 		if config.AckPolicy != AckExplicit {
-			return nil, NewJSConsumerPullRequiresAckError()
+			return nil, ApiErrors[JSConsumerPullRequiresAckErr]
 		}
 		// They are also required to be durable since otherwise we will not know when to
 		// clean them up.
 		if config.Durable == _EMPTY_ {
-			return nil, NewJSConsumerPullNotDurableError()
+			return nil, ApiErrors[JSConsumerPullNotDurableErr]
 		}
 		if config.RateLimit > 0 {
-			return nil, NewJSConsumerPullWithRateLimitError()
+			return nil, ApiErrors[JSConsumerPullWithRateLimitErr]
 		}
 		if config.MaxWaiting < 0 {
-			return nil, NewJSConsumerMaxWaitingNegativeError()
+			return nil, ApiErrors[JSConsumerMaxWaitingNegativeErr]
 		}
 		// Set to default if not specified.
 		if config.MaxWaiting == 0 {
 			config.MaxWaiting = JSWaitQueueDefaultMax
 		}
 		if config.Heartbeat > 0 {
-			return nil, NewJSConsumerHBRequiresPushError()
+			return nil, ApiErrors[JSConsumerHBRequiresPushErr]
 		}
 		if config.FlowControl {
-			return nil, NewJSConsumerFCRequiresPushError()
+			return nil, ApiErrors[JSConsumerFCRequiresPushErr]
 		}
 	}
 
 	// Direct need to be non-mapped ephemerals.
 	if config.Direct {
 		if config.DeliverSubject == _EMPTY_ {
-			return nil, NewJSConsumerDirectRequiresPushError()
+			return nil, ApiErrors[JSConsumerDirectRequiresPushErr]
 		}
 		if isDurableConsumer(config) {
-			return nil, NewJSConsumerDirectRequiresEphemeralError()
+			return nil, ApiErrors[JSConsumerDirectRequiresEphemeralErr]
 		}
 		if ca != nil {
-			return nil, NewJSConsumerOnMappedError()
+			return nil, ApiErrors[JSConsumerOnMappedErr]
 		}
 	}
 
@@ -351,7 +351,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		config.MaxDeliver = -1
 	}
 	// Set proper default for max ack pending if we are ack explicit and none has been set.
-	if (config.AckPolicy == AckExplicit || config.AckPolicy == AckAll) && config.MaxAckPending == 0 {
+	if config.AckPolicy == AckExplicit && config.MaxAckPending == 0 {
 		config.MaxAckPending = JsDefaultMaxAckPending
 	}
 
@@ -359,7 +359,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 	if config.FilterSubject != _EMPTY_ {
 		subjects, hasExt := mset.allSubjects()
 		if !validFilteredSubject(config.FilterSubject, subjects) && !hasExt {
-			return nil, NewJSConsumerFilterNotSubsetError()
+			return nil, ApiErrors[JSConsumerFilterNotSubsetErr]
 		}
 	}
 
@@ -367,24 +367,30 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 	switch config.DeliverPolicy {
 	case DeliverAll:
 		if config.OptStartSeq > 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver all, but optional start sequence is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver all, but optional start sequence is also set")
 		}
 		if config.OptStartTime != nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver all, but optional start time is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver all, but optional start time is also set")
 		}
 	case DeliverLast:
 		if config.OptStartSeq > 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last, but optional start sequence is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last, but optional start sequence is also set")
 		}
 		if config.OptStartTime != nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last, but optional start time is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last, but optional start time is also set")
 		}
 	case DeliverLastPerSubject:
 		if config.OptStartSeq > 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but optional start sequence is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last per subject, but optional start sequence is also set")
 		}
 		if config.OptStartTime != nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but optional start time is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last per subject, but optional start time is also set")
 		}
 		badConfig := config.FilterSubject == _EMPTY_
 		if !badConfig {
@@ -394,28 +400,35 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 			}
 		}
 		if badConfig {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but filter subject is not set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last per subject, but filter subject is not set")
 		}
 	case DeliverNew:
 		if config.OptStartSeq > 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver new, but optional start sequence is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver new, but optional start sequence is also set")
 		}
 		if config.OptStartTime != nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver new, but optional start time is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver new, but optional start time is also set")
 		}
 	case DeliverByStartSequence:
 		if config.OptStartSeq == 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver by start sequence, but optional start sequence is not set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver by start sequence, but optional start sequence is not set")
 		}
 		if config.OptStartTime != nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver by start sequence, but optional start time is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver by start sequence, but optional start time is also set")
 		}
 	case DeliverByStartTime:
 		if config.OptStartTime == nil {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver by start time, but optional start time is not set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver by start time, but optional start time is not set")
 		}
 		if config.OptStartSeq != 0 {
-			return nil, NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver by start time, but optional start sequence is also set"))
+			return nil, ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver by start time, but optional start sequence is also set")
 		}
 	}
 
@@ -424,14 +437,14 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		s := strings.TrimSuffix(config.SampleFrequency, "%")
 		sampleFreq, err = strconv.Atoi(s)
 		if err != nil {
-			return nil, NewJSConsumerInvalidSamplingError(err)
+			return nil, ApiErrors[JSConsumerInvalidSamplingErrF].NewT("{err}", err)
 		}
 	}
 
 	// Grab the client, account and server reference.
 	c := mset.client
 	if c == nil {
-		return nil, NewJSStreamInvalidError()
+		return nil, ApiErrors[JSStreamInvalidErr]
 	}
 	c.mu.Lock()
 	s, a := c.srv, c.acc
@@ -458,7 +471,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 					eo.updateDeliverSubject(config.DeliverSubject)
 					return eo, nil
 				} else {
-					return nil, NewJSConsumerNameExistError()
+					return nil, ApiErrors[JSConsumerNameExistErr]
 				}
 			}
 		}
@@ -474,7 +487,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 	}
 	if maxc > 0 && len(mset.consumers) >= maxc {
 		mset.mu.Unlock()
-		return nil, NewJSMaximumConsumersLimitError()
+		return nil, ApiErrors[JSMaximumConsumersLimitErr]
 	}
 
 	// Check on stream type conflicts with WorkQueues.
@@ -482,22 +495,22 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		// Force explicit acks here.
 		if config.AckPolicy != AckExplicit {
 			mset.mu.Unlock()
-			return nil, NewJSConsumerWQRequiresExplicitAckError()
+			return nil, ApiErrors[JSConsumerWQRequiresExplicitAckErr]
 		}
 
 		if len(mset.consumers) > 0 {
 			if config.FilterSubject == _EMPTY_ {
 				mset.mu.Unlock()
-				return nil, NewJSConsumerWQMultipleUnfilteredError()
+				return nil, ApiErrors[JSConsumerWQMultipleUnfilteredErr]
 			} else if !mset.partitionUnique(config.FilterSubject) {
 				// We have a partition but it is not unique amongst the others.
 				mset.mu.Unlock()
-				return nil, NewJSConsumerWQConsumerNotUniqueError()
+				return nil, ApiErrors[JSConsumerWQConsumerNotUniqueErr]
 			}
 		}
 		if config.DeliverPolicy != DeliverAll {
 			mset.mu.Unlock()
-			return nil, NewJSConsumerWQConsumerNotDeliverAllError()
+			return nil, ApiErrors[JSConsumerWQConsumerNotDeliverAllErr]
 		}
 	}
 
@@ -530,7 +543,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		if len(config.Durable) > JSMaxNameLen {
 			mset.mu.Unlock()
 			o.deleteWithoutAdvisory()
-			return nil, NewJSConsumerNameTooLongError(JSMaxNameLen)
+			return nil, ApiErrors[JSConsumerNameTooLongErrF].NewT("{max}", JSMaxNameLen)
 		}
 		o.name = config.Durable
 		if o.isPullMode() {
@@ -578,7 +591,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 	if !isValidName(o.name) {
 		mset.mu.Unlock()
 		o.deleteWithoutAdvisory()
-		return nil, NewJSConsumerBadDurableNameError()
+		return nil, ApiErrors[JSConsumerBadDurableNameErr]
 	}
 
 	// Select starting sequence number
@@ -589,7 +602,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		if err != nil {
 			mset.mu.Unlock()
 			o.deleteWithoutAdvisory()
-			return nil, NewJSConsumerStoreFailedError(err)
+			return nil, ApiErrors[JSConsumerStoreFailedErrF].NewT("{err}", err)
 		}
 		o.store = store
 	}
@@ -601,20 +614,20 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri
 		if !o.isDurable() || !o.isPushMode() {
 			o.name = _EMPTY_ // Prevent removal since same name.
 			o.deleteWithoutAdvisory()
-			return nil, NewJSConsumerNameExistError()
+			return nil, ApiErrors[JSConsumerNameExistErr]
 		}
 		// If we are here we have already registered this durable. If it is still active that is an error.
 		if eo.isActive() {
 			o.name = _EMPTY_ // Prevent removal since same name.
 			o.deleteWithoutAdvisory()
-			return nil, NewJSConsumerExistingActiveError()
+			return nil, ApiErrors[JSConsumerExistingActiveErr]
 		}
 		// Since we are here this means we have a potentially new durable so we should update here.
 		// Check that configs are the same.
 		if !configsEqualSansDelivery(o.cfg, eo.cfg) {
 			o.name = _EMPTY_ // Prevent removal since same name.
 			o.deleteWithoutAdvisory()
-			return nil, NewJSConsumerReplacementWithDifferentNameError()
+			return nil, ApiErrors[JSConsumerReplacementWithDifferentNameErr]
 		}
 		// Once we are here we have a replacement push-based durable.
 		eo.updateDeliverSubject(o.cfg.DeliverSubject)
@@ -2113,7 +2126,6 @@ func (o *consumer) loopAndGatherMsgs(qch chan struct{}) {
 			if !o.active {
 				goto waitForMsgs
 			}
-			// Flowcontrol.
 			if o.maxpb > 0 && o.pbytes > o.maxpb {
 				goto waitForMsgs
 			}
@@ -2209,15 +2221,15 @@ func (o *consumer) loopAndGatherMsgs(qch chan struct{}) {
 			if o.isActive() {
 				const t = "NATS/1.0 100 Idle Heartbeat\r\n%s: %d\r\n%s: %d\r\n\r\n"
 				hdr := []byte(fmt.Sprintf(t, JSLastConsumerSeq, dseq, JSLastStreamSeq, sseq))
-				if fcp := o.fcID(); fcp != _EMPTY_ {
-					// Add in that we are stalled on flow control here.
-					addOn := []byte(fmt.Sprintf("%s: %s\r\n\r\n", JSConsumerStalled, fcp))
-					hdr = append(hdr[:len(hdr)-LEN_CR_LF], []byte(addOn)...)
-				}
 				outq.send(&jsPubMsg{odsubj, _EMPTY_, _EMPTY_, hdr, nil, nil, 0, nil})
 			}
 			// Reset our idle heartbeat timer.
 			hb.Reset(hbd)
+
+			// Now check on flowcontrol if enabled. Make sure if we have any outstanding to resend.
+			if o.fcOut() {
+				o.sendFlowControl()
+			}
 		}
 	}
 }
@@ -2324,10 +2336,12 @@ func (o *consumer) processFlowControl(_ *subscription, c *client, _ *Account, su
 
 	// Update accounting.
 	o.pbytes -= o.fcsz
+	o.fcid, o.fcsz = _EMPTY_, 0
+
+	// In case they are sent out of order or we get duplicates etc.
 	if o.pbytes < 0 {
 		o.pbytes = 0
 	}
-	o.fcid, o.fcsz = _EMPTY_, 0
 
 	o.signalNewMessages()
 }
@@ -2350,10 +2364,10 @@ func (o *consumer) fcReply() string {
 	return sb.String()
 }
 
-func (o *consumer) fcID() string {
+func (o *consumer) fcOut() bool {
 	o.mu.RLock()
 	defer o.mu.RUnlock()
-	return o.fcid
+	return o.fcid != _EMPTY_
 }
 
 // sendFlowControl will send a flow control packet to the consumer.
diff --git a/server/errors_gen.go b/server/errors_gen.go
index 03e087c9..deea51e0 100644
--- a/server/errors_gen.go
+++ b/server/errors_gen.go
@@ -9,23 +9,17 @@ import (
 	"log"
 	"os"
 	"os/exec"
-	"regexp"
 	"sort"
-	"strings"
 	"text/template"
 
 	"github.com/nats-io/nats-server/v2/server"
 )
 
-var tagRe = regexp.MustCompile("\\{(.+?)}")
-
 var templ = `
 // Generated code, do not edit. See errors.json and run go generate to update
 
 package server
 
-import "strings"
-
 const (
 {{- range $i, $error := . }}
 {{- if .Comment }}
@@ -50,28 +44,6 @@ var (
 {{- end }}
 {{- end }}
 )
-
-{{- range $i, $error := . }}
-// {{ .Constant | funcNameForConstant }} creates a new {{ .Constant }} error: {{ .Description | printf "%q" }}
-func {{ .Constant | funcNameForConstant }}({{ .Description | funcArgsForTags }}) *ApiError {
-    eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
- 	}
-{{ if .Description | hasTags }}
-	e:=ApiErrors[{{.Constant}}]
-	args:=e.toReplacerArgs([]interface{}{ {{.Description | replacerArgsForTags }} })
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-{{- else }}
-	return ApiErrors[{{.Constant}}]
-{{- end }}
-}
-
-{{- end }}
 `
 
 func panicIfErr(err error) {
@@ -120,21 +92,6 @@ func checkDupes(errs []server.ErrorsData) error {
 	return nil
 }
 
-func findTags(d string) []string {
-	tags := []string{}
-	for _, tag := range tagRe.FindAllStringSubmatch(d, -1) {
-		if len(tag) != 2 {
-			continue
-		}
-
-		tags = append(tags, tag[1])
-	}
-
-	sort.Strings(tags)
-
-	return tags
-}
-
 func main() {
 	ej, err := os.ReadFile("server/errors.json")
 	panicIfErr(err)
@@ -147,60 +104,7 @@ func main() {
 		return errs[i].Constant < errs[j].Constant
 	})
 
-	t := template.New("errors").Funcs(
-		template.FuncMap{
-			"inc": func(i int) int { return i + 1 },
-			"hasTags": func(d string) bool {
-				return strings.Contains(d, "{") && strings.Contains(d, "}")
-			},
-			"replacerArgsForTags": func(d string) string {
-				res := []string{}
-				for _, tag := range findTags(d) {
-					res = append(res, `"{`+tag+`}"`)
-					res = append(res, tag)
-				}
-
-				return strings.Join(res, ", ")
-			},
-			"funcArgsForTags": func(d string) string {
-				res := []string{}
-				for _, tag := range findTags(d) {
-					if tag == "err" {
-						res = append(res, "err error")
-					} else if tag == "seq" {
-						res = append(res, "seq uint64")
-					} else {
-						res = append(res, fmt.Sprintf("%s interface{}", tag))
-					}
-				}
-
-				res = append(res, "opts ...ErrorOption")
-
-				return strings.Join(res, ", ")
-			},
-			"funcNameForConstant": func(c string) string {
-				res := ""
-
-				switch {
-				case strings.HasSuffix(c, "ErrF"):
-					res = fmt.Sprintf("New%sError", strings.TrimSuffix(c, "ErrF"))
-				case strings.HasSuffix(c, "Err"):
-					res = fmt.Sprintf("New%sError", strings.TrimSuffix(c, "Err"))
-				case strings.HasSuffix(c, "ErrorF"):
-					res = fmt.Sprintf("New%s", strings.TrimSuffix(c, "F"))
-				case strings.HasSuffix(c, "F"):
-					res = fmt.Sprintf("New%sError", strings.TrimSuffix(c, "F"))
-				default:
-					res = fmt.Sprintf("New%s", c)
-				}
-
-				if !strings.HasSuffix(res, "Error") {
-					res = fmt.Sprintf("%sError", res)
-				}
-
-				return res
-			},
-		})
+	t := template.New("errors").Funcs(template.FuncMap{"inc": func(i int) int { return i + 1 }})
 	p, err := t.Parse(templ)
 	panicIfErr(err)
 
diff --git a/server/jetstream.go b/server/jetstream.go
index a06427d9..a4836a7a 100644
--- a/server/jetstream.go
+++ b/server/jetstream.go
@@ -867,7 +867,7 @@ func (s *Server) JetStreamNumAccounts() int {
 func (s *Server) JetStreamReservedResources() (int64, int64, error) {
 	js := s.getJetStream()
 	if js == nil {
-		return -1, -1, NewJSNotEnabledForAccountError()
+		return -1, -1, ApiErrors[JSNotEnabledForAccountErr]
 	}
 	js.mu.RLock()
 	defer js.mu.RUnlock()
@@ -911,7 +911,7 @@ func (a *Account) EnableJetStream(limits *JetStreamAccountLimits) error {
 	js := s.getJetStream()
 	if js == nil {
 		a.assignJetStreamLimits(limits)
-		return NewJSNotEnabledError()
+		return ApiErrors[JSNotEnabledErr]
 	}
 
 	if s.SystemAccount() == a {
@@ -1227,14 +1227,14 @@ func (a *Account) lookupStream(name string) (*stream, error) {
 	a.mu.RUnlock()
 
 	if jsa == nil {
-		return nil, NewJSNotEnabledForAccountError()
+		return nil, ApiErrors[JSNotEnabledForAccountErr]
 	}
 	jsa.mu.Lock()
 	defer jsa.mu.Unlock()
 
 	mset, ok := jsa.streams[name]
 	if !ok {
-		return nil, NewJSStreamNotFoundError()
+		return nil, ApiErrors[JSStreamNotFoundErr]
 	}
 	return mset, nil
 }
@@ -1251,10 +1251,10 @@ func (a *Account) UpdateJetStreamLimits(limits *JetStreamAccountLimits) error {
 	}
 	js := s.getJetStream()
 	if js == nil {
-		return NewJSNotEnabledError()
+		return ApiErrors[JSNotEnabledErr]
 	}
 	if jsa == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	if limits == nil {
@@ -1348,7 +1348,7 @@ func (a *Account) removeJetStream() error {
 
 	js := s.getJetStream()
 	if js == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	return js.disableJetStream(js.lookupAccount(a))
@@ -1357,7 +1357,7 @@ func (a *Account) removeJetStream() error {
 // Disable JetStream for the account.
 func (js *jetStream) disableJetStream(jsa *jsAccount) error {
 	if jsa == nil || jsa.account == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	js.mu.Lock()
@@ -1531,11 +1531,11 @@ func (jsa *jsAccount) limitsExceeded(storeType StorageType) bool {
 // Lock should be held.
 func (jsa *jsAccount) checkLimits(config *StreamConfig) error {
 	if jsa.limits.MaxStreams > 0 && len(jsa.streams) >= jsa.limits.MaxStreams {
-		return NewJSMaximumStreamsLimitError()
+		return ApiErrors[JSMaximumStreamsLimitErr]
 	}
 	// Check MaxConsumers
 	if config.MaxConsumers > 0 && jsa.limits.MaxConsumers > 0 && config.MaxConsumers > jsa.limits.MaxConsumers {
-		return NewJSMaximumConsumersLimitError()
+		return ApiErrors[JSMaximumConsumersLimitErr]
 	}
 
 	// Check storage, memory or disk.
@@ -1559,24 +1559,24 @@ func (jsa *jsAccount) checkBytesLimits(addBytes int64, storage StorageType, repl
 		// Account limits defined.
 		if jsa.limits.MaxMemory > 0 {
 			if jsa.memReserved+totalBytes > jsa.limits.MaxMemory {
-				return NewJSMemoryResourcesExceededError()
+				return ApiErrors[JSMemoryResourcesExceededErr]
 			}
 		} else {
 			// Account is unlimited, check if this server can handle request.
 			if js.memReserved+addBytes > js.config.MaxMemory {
-				return NewJSMemoryResourcesExceededError()
+				return ApiErrors[JSMemoryResourcesExceededErr]
 			}
 		}
 	case FileStorage:
 		// Account limits defined.
 		if jsa.limits.MaxStore > 0 {
 			if jsa.storeReserved+totalBytes > jsa.limits.MaxStore {
-				return NewJSStorageResourcesExceededError()
+				return ApiErrors[JSStorageResourcesExceededErr]
 			}
 		} else {
 			// Account is unlimited, check if this server can handle request.
 			if js.storeReserved+addBytes > js.config.MaxStore {
-				return NewJSStorageResourcesExceededError()
+				return ApiErrors[JSStorageResourcesExceededErr]
 			}
 		}
 	}
@@ -1656,10 +1656,10 @@ func (js *jetStream) sufficientResources(limits *JetStreamAccountLimits) error {
 	}
 
 	if js.memReserved+limits.MaxMemory > js.config.MaxMemory {
-		return NewJSMemoryResourcesExceededError()
+		return ApiErrors[JSMemoryResourcesExceededErr]
 	}
 	if js.storeReserved+limits.MaxStore > js.config.MaxStore {
-		return NewJSStorageResourcesExceededError()
+		return ApiErrors[JSStorageResourcesExceededErr]
 	}
 	return nil
 }
@@ -1747,7 +1747,7 @@ func (a *Account) checkForJetStream() (*Server, *jsAccount, error) {
 	a.mu.RUnlock()
 
 	if s == nil || jsa == nil {
-		return nil, nil, NewJSNotEnabledForAccountError()
+		return nil, nil, ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	return s, jsa, nil
@@ -1957,7 +1957,7 @@ func (t *streamTemplate) delete() error {
 	t.mu.Unlock()
 
 	if jsa == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	jsa.mu.Lock()
@@ -2001,7 +2001,7 @@ func (t *streamTemplate) delete() error {
 func (a *Account) deleteStreamTemplate(name string) error {
 	t, err := a.lookupStreamTemplate(name)
 	if err != nil {
-		return NewJSStreamTemplateNotFoundError()
+		return ApiErrors[JSStreamTemplateNotFoundErr]
 	}
 	return t.delete()
 }
diff --git a/server/jetstream_api.go b/server/jetstream_api.go
index 6806c65e..561a1270 100644
--- a/server/jetstream_api.go
+++ b/server/jetstream_api.go
@@ -633,7 +633,7 @@ func (js *jetStream) apiDispatch(sub *subscription, c *client, acc *Account, sub
 		atomic.AddInt64(&js.apiCalls, -1)
 		ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
 		if err == nil {
-			resp := &ApiResponse{Type: JSApiOverloadedType, Error: NewJSInsufficientResourcesError()}
+			resp := &ApiResponse{Type: JSApiOverloadedType, Error: ApiErrors[JSInsufficientResourcesErr]}
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		} else {
 			s.Warnf(badAPIRequestT, rmsg)
@@ -662,7 +662,7 @@ func (js *jetStream) apiDispatch(sub *subscription, c *client, acc *Account, sub
 func (s *Server) setJetStreamExportSubs() error {
 	js := s.getJetStream()
 	if js == nil {
-		return NewJSNotEnabledError()
+		return ApiErrors[JSNotEnabledErr]
 	}
 
 	// This is the catch all now for all JetStream API calls.
@@ -847,7 +847,7 @@ func (s *Server) jsAccountInfoRequest(sub *subscription, c *client, _ *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -861,7 +861,7 @@ func (s *Server) jsAccountInfoRequest(sub *subscription, c *client, _ *Account,
 		if !doErr {
 			return
 		}
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 	} else {
 		stats := acc.JetStreamUsage()
 		resp.JetStreamAccountStats = &stats
@@ -900,34 +900,34 @@ func (s *Server) jsTemplateCreateRequest(sub *subscription, c *client, _ *Accoun
 
 	var resp = JSApiStreamTemplateCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateCreateResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Not supported for now.
 	if s.JetStreamIsClustered() {
-		resp.Error = NewJSClusterUnSupportFeatureError()
+		resp.Error = ApiErrors[JSClusterUnSupportFeatureErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	var cfg StreamTemplateConfig
 	if err := json.Unmarshal(msg, &cfg); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	templateName := templateNameFromSubject(subject)
 	if templateName != cfg.Name {
-		resp.Error = NewJSTemplateNameNotMatchSubjectError()
+		resp.Error = ApiErrors[JSTemplateNameNotMatchSubjectErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	t, err := acc.addStreamTemplate(&cfg)
 	if err != nil {
-		resp.Error = NewJSStreamTemplateCreateError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamTemplateCreateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -955,14 +955,14 @@ func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, _ *Account
 
 	var resp = JSApiStreamTemplateNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateNamesResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Not supported for now.
 	if s.JetStreamIsClustered() {
-		resp.Error = NewJSClusterUnSupportFeatureError()
+		resp.Error = ApiErrors[JSClusterUnSupportFeatureErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -971,7 +971,7 @@ func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, _ *Account
 	if !isEmptyRequest(msg) {
 		var req JSApiStreamTemplatesRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1019,19 +1019,19 @@ func (s *Server) jsTemplateInfoRequest(sub *subscription, c *client, _ *Account,
 
 	var resp = JSApiStreamTemplateInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateInfoResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSNotEmptyRequestError()
+		resp.Error = ApiErrors[JSNotEmptyRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	name := templateNameFromSubject(subject)
 	t, err := acc.lookupStreamTemplate(name)
 	if err != nil {
-		resp.Error = NewJSStreamTemplateNotFoundError()
+		resp.Error = ApiErrors[JSStreamTemplateNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1060,19 +1060,19 @@ func (s *Server) jsTemplateDeleteRequest(sub *subscription, c *client, _ *Accoun
 
 	var resp = JSApiStreamTemplateDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateDeleteResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSNotEmptyRequestError()
+		resp.Error = ApiErrors[JSNotEmptyRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	name := templateNameFromSubject(subject)
 	err = acc.deleteStreamTemplate(name)
 	if err != nil {
-		resp.Error = NewJSStreamTemplateDeleteError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamTemplateDeleteErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1109,7 +1109,7 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1121,20 +1121,20 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	var cfg StreamConfig
 	if err := json.Unmarshal(msg, &cfg); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	streamName := streamNameFromSubject(subject)
 	if streamName != cfg.Name {
-		resp.Error = NewJSStreamMismatchError()
+		resp.Error = ApiErrors[JSStreamMismatchErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1168,22 +1168,22 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 	// Do some pre-checking for mirror config to avoid cycles in clustered mode.
 	if cfg.Mirror != nil {
 		if len(cfg.Subjects) > 0 {
-			resp.Error = NewJSMirrorWithSubjectsError()
+			resp.Error = ApiErrors[JSMirrorWithSubjectsErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if len(cfg.Sources) > 0 {
-			resp.Error = NewJSMirrorWithSourcesError()
+			resp.Error = ApiErrors[JSMirrorWithSourcesErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if cfg.Mirror.FilterSubject != _EMPTY_ {
-			resp.Error = NewJSMirrorWithSubjectFiltersError()
+			resp.Error = ApiErrors[JSMirrorWithSubjectFiltersErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if cfg.Mirror.OptStartSeq > 0 && cfg.Mirror.OptStartTime != nil {
-			resp.Error = NewJSMirrorWithStartSeqAndTimeError()
+			resp.Error = ApiErrors[JSMirrorWithStartSeqAndTimeErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1198,7 +1198,7 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 			streamSubs = append(streamSubs, subs...)
 		}
 		if exists && cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
-			resp.Error = NewJSMirrorMaxMessageSizeTooBigError()
+			resp.Error = ApiErrors[JSMirrorMaxMessageSizeTooBigErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1227,7 +1227,7 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 				apiPrefixes = append(apiPrefixes, src.External.ApiPrefix)
 			}
 			if exists && cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
-				resp.Error = NewJSSourceMaxMessageSizeTooBigError()
+				resp.Error = ApiErrors[JSSourceMaxMessageSizeTooBigErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				return
 			}
@@ -1236,13 +1236,13 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 	// check prefix overlap with subjects
 	for _, pfx := range deliveryPrefixes {
 		if !IsValidPublishSubject(pfx) {
-			resp.Error = NewJSStreamInvalidExternalDeliverySubjError(pfx)
+			resp.Error = ApiErrors[JSStreamInvalidExternalDeliverySubjErrF].NewT("{prefix}", pfx)
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		for _, sub := range streamSubs {
 			if SubjectsCollide(sub, fmt.Sprintf("%s.%s", pfx, sub)) {
-				resp.Error = NewJSStreamExternalDelPrefixOverlapsError(pfx, sub)
+				resp.Error = ApiErrors[JSStreamExternalDelPrefixOverlapsErrF].NewT("{prefix}", pfx, "{subject}", sub)
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				return
 			}
@@ -1256,7 +1256,7 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 			return
 		}
 		if SubjectsCollide(apiPfx, JSApiPrefix) {
-			resp.Error = NewJSStreamExternalApiOverlapError(apiPfx, JSApiPrefix)
+			resp.Error = ApiErrors[JSStreamExternalApiOverlapErrF].NewT("{prefix}", apiPfx, "{subject}", JSApiPrefix)
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1269,7 +1269,7 @@ func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, a *Account,
 
 	mset, err := acc.addStream(&cfg)
 	if err != nil {
-		resp.Error = NewJSStreamCreateError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamCreateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1298,7 +1298,7 @@ func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, _ *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1310,28 +1310,28 @@ func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, _ *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	var ncfg StreamConfig
 	if err := json.Unmarshal(msg, &ncfg); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	cfg, err := checkStreamCfg(&ncfg)
 	if err != nil {
-		resp.Error = NewJSStreamInvalidConfigError(err)
+		resp.Error = ApiErrors[JSStreamInvalidConfigF].NewT("{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	streamName := streamNameFromSubject(subject)
 	if streamName != cfg.Name {
-		resp.Error = NewJSStreamMismatchError()
+		resp.Error = ApiErrors[JSStreamMismatchErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1343,13 +1343,13 @@ func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, _ *Account,
 
 	mset, err := acc.lookupStream(streamName)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	if err := mset.update(&cfg); err != nil {
-		resp.Error = NewJSStreamUpdateError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamUpdateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1380,7 +1380,7 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1392,7 +1392,7 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -1404,7 +1404,7 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account,
 	if !isEmptyRequest(msg) {
 		var req JSApiStreamNamesRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1425,7 +1425,7 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account,
 		}
 		js.mu.RLock()
 		for stream, sa := range cc.streams[acc.Name] {
-			if IsNatsErr(sa.err, JSClusterNotAssignedErr) {
+			if sa.err == ApiErrors[JSClusterNotAssignedErr] {
 				continue
 			}
 			if filter != _EMPTY_ {
@@ -1507,7 +1507,7 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, s
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1519,7 +1519,7 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, s
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -1529,7 +1529,7 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, s
 	if !isEmptyRequest(msg) {
 		var req JSApiStreamNamesRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1605,18 +1605,18 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, s
 			// We can't find the stream, so mimic what would be the errors below.
 			if hasJS, doErr := acc.checkJetStream(); !hasJS {
 				if doErr {
-					resp.Error = NewJSNotEnabledForAccountError()
+					resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				}
 				return
 			}
 			// No stream present.
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		} else if sa == nil {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				// Delaying an error response gives the leader a chance to respond before us
 				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
 			}
@@ -1629,7 +1629,7 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, s
 		// We have the stream assigned and a leader, so only the stream leader should answer.
 		if !acc.JetStreamIsStreamLeader(streamName) && !isLeaderless {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				// Delaying an error response gives the leader a chance to respond before us
 				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), sa.Group)
 			}
@@ -1639,7 +1639,7 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, s
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -1649,7 +1649,7 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, s
 	if !isEmptyRequest(msg) {
 		var req JSApiStreamInfoRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -1658,7 +1658,7 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, s
 
 	mset, err := acc.lookupStream(streamName)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1704,7 +1704,7 @@ func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *
 
 	// If we are not in clustered mode this is a failed request.
 	if !s.JetStreamIsClustered() {
-		resp.Error = NewJSClusterRequiredError()
+		resp.Error = ApiErrors[JSClusterRequiredErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1715,7 +1715,7 @@ func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *
 		return
 	}
 	if js.isLeaderless() {
-		resp.Error = NewJSClusterNotAvailError()
+		resp.Error = ApiErrors[JSClusterNotAvailErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1725,7 +1725,7 @@ func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *
 	js.mu.RUnlock()
 
 	if isLeader && sa == nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	} else if sa == nil {
@@ -1734,20 +1734,20 @@ func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Check to see if we are a member of the group and if the group has no leader.
 	if js.isGroupLeaderless(sa.Group) {
-		resp.Error = NewJSClusterNotAvailError()
+		resp.Error = ApiErrors[JSClusterNotAvailErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1759,7 +1759,7 @@ func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *
 
 	mset, err := acc.lookupStream(name)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1790,7 +1790,7 @@ func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _
 
 	// If we are not in clustered mode this is a failed request.
 	if !s.JetStreamIsClustered() {
-		resp.Error = NewJSClusterRequiredError()
+		resp.Error = ApiErrors[JSClusterRequiredErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1801,7 +1801,7 @@ func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _
 		return
 	}
 	if js.isLeaderless() {
-		resp.Error = NewJSClusterNotAvailError()
+		resp.Error = ApiErrors[JSClusterNotAvailErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1815,7 +1815,7 @@ func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _
 	js.mu.RUnlock()
 
 	if isLeader && sa == nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	} else if sa == nil {
@@ -1826,13 +1826,13 @@ func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _
 		ca = sa.consumers[consumer]
 	}
 	if ca == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	// Check to see if we are a member of the group and if the group has no leader.
 	if js.isGroupLeaderless(ca.Group) {
-		resp.Error = NewJSClusterNotAvailError()
+		resp.Error = ApiErrors[JSClusterNotAvailErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1843,26 +1843,26 @@ func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	o := mset.lookupConsumer(consumer)
 	if o == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1892,7 +1892,7 @@ func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Acco
 
 	// If we are not in clustered mode this is a failed request.
 	if !s.JetStreamIsClustered() {
-		resp.Error = NewJSClusterRequiredError()
+		resp.Error = ApiErrors[JSClusterRequiredErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1903,7 +1903,7 @@ func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Acco
 		return
 	}
 	if js.isLeaderless() {
-		resp.Error = NewJSClusterNotAvailError()
+		resp.Error = ApiErrors[JSClusterNotAvailErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1919,32 +1919,32 @@ func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Acco
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	var req JSApiStreamRemovePeerRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if req.Peer == _EMPTY_ {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	if sa == nil {
 		// No stream present.
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -1960,14 +1960,14 @@ func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Acco
 
 	// Make sure we are a member.
 	if !isMember {
-		resp.Error = NewJSClusterPeerNotMemberError()
+		resp.Error = ApiErrors[JSClusterPeerNotMemberErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	// If we are here we have a valid peer member set for removal.
 	if !js.removePeerFromStream(sa, nodeName) {
-		resp.Error = NewJSPeerRemapError()
+		resp.Error = ApiErrors[JSPeerRemapErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2005,14 +2005,14 @@ func (s *Server) jsLeaderServerRemoveRequest(sub *subscription, c *client, _ *Ac
 	var resp = JSApiMetaServerRemoveResponse{ApiResponse: ApiResponse{Type: JSApiMetaServerRemoveResponseType}}
 
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	var req JSApiMetaServerRemoveRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2029,7 +2029,7 @@ func (s *Server) jsLeaderServerRemoveRequest(sub *subscription, c *client, _ *Ac
 	js.mu.RUnlock()
 
 	if found == _EMPTY_ {
-		resp.Error = NewJSClusterServerNotMemberError()
+		resp.Error = ApiErrors[JSClusterServerNotMemberErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2076,13 +2076,13 @@ func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Accoun
 	if !isEmptyRequest(msg) {
 		var req JSApiLeaderStepdownRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if len(req.Placement.Tags) > 0 {
 			// Tags currently not supported.
-			resp.Error = NewJSClusterTagsError()
+			resp.Error = ApiErrors[JSClusterTagsErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2098,7 +2098,7 @@ func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Accoun
 			}
 		}
 		if len(peers) == 0 {
-			resp.Error = NewJSClusterNoPeersError()
+			resp.Error = ApiErrors[JSClusterNoPeersErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2112,7 +2112,7 @@ func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Accoun
 	// Call actual stepdown.
 	err = cc.meta.StepDown(preferredLeader)
 	if err != nil {
-		resp.Error = NewJSRaftGeneralError(err, Unless(err))
+		resp.Error = ApiErrors[JSRaftGeneralErrF].ErrOrNewT(err, "{err}", err)
 	} else {
 		resp.Success = true
 	}
@@ -2158,7 +2158,7 @@ func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, _ *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2170,14 +2170,14 @@ func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, _ *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSNotEmptyRequestError()
+		resp.Error = ApiErrors[JSNotEmptyRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2191,13 +2191,13 @@ func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, _ *Account,
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	if err := mset.delete(); err != nil {
-		resp.Error = NewJSStreamDeleteError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamDeleteErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2229,7 +2229,7 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2242,13 +2242,13 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su
 			// We can't find the stream, so mimic what would be the errors below.
 			if hasJS, doErr := acc.checkJetStream(); !hasJS {
 				if doErr {
-					resp.Error = NewJSNotEnabledForAccountError()
+					resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				}
 				return
 			}
 			// No stream present.
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		} else if sa == nil {
@@ -2257,7 +2257,7 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su
 
 		// Check to see if we are a member of the group and if the group has no leader.
 		if js.isGroupLeaderless(sa.Group) {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2270,26 +2270,26 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	var req JSApiMsgDeleteRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2306,9 +2306,9 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su
 		removed, err = mset.eraseMsg(req.Seq)
 	}
 	if err != nil {
-		resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamMsgDeleteFailedF].ErrOrNewT(err, "{err}", err)
 	} else if !removed {
-		resp.Error = NewJSSequenceNotFoundError(req.Seq)
+		resp.Error = ApiErrors[JSSequenceNotFoundErrF].NewT("{seq}", req.Seq)
 	} else {
 		resp.Success = true
 	}
@@ -2338,7 +2338,7 @@ func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subje
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2351,13 +2351,13 @@ func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subje
 			// We can't find the stream, so mimic what would be the errors below.
 			if hasJS, doErr := acc.checkJetStream(); !hasJS {
 				if doErr {
-					resp.Error = NewJSNotEnabledForAccountError()
+					resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				}
 				return
 			}
 			// No stream present.
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		} else if sa == nil {
@@ -2366,7 +2366,7 @@ func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subje
 
 		// Check to see if we are a member of the group and if the group has no leader.
 		if js.isGroupLeaderless(sa.Group) {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2379,33 +2379,33 @@ func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subje
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	var req JSApiMsgGetRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Check that we do not have both options set.
 	if req.Seq > 0 && req.LastFor != _EMPTY_ || req.Seq == 0 && req.LastFor == _EMPTY_ {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2421,7 +2421,7 @@ func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subje
 		subj, seq, hdr, msg, ts, err = mset.store.LoadLastMsg(req.LastFor)
 	}
 	if err != nil {
-		resp.Error = NewJSNoMessageFoundError()
+		resp.Error = ApiErrors[JSNoMessageFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2466,18 +2466,18 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 			// We can't find the stream, so mimic what would be the errors below.
 			if hasJS, doErr := acc.checkJetStream(); !hasJS {
 				if doErr {
-					resp.Error = NewJSNotEnabledForAccountError()
+					resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				}
 				return
 			}
 			// No stream present.
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		} else if sa == nil {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			}
 			return
@@ -2485,7 +2485,7 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 
 		// Check to see if we are a member of the group and if the group has no leader.
 		if js.isGroupLeaderless(sa.Group) {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2493,7 +2493,7 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 		// We have the stream assigned and a leader, so only the stream leader should answer.
 		if !acc.JetStreamIsStreamLeader(stream) {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			}
 			return
@@ -2502,7 +2502,7 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -2512,12 +2512,12 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 	if !isEmptyRequest(msg) {
 		var req JSApiStreamPurgeRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if req.Sequence > 0 && req.Keep > 0 {
-			resp.Error = NewJSBadRequestError()
+			resp.Error = ApiErrors[JSBadRequestErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2526,7 +2526,7 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2538,7 +2538,7 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account,
 
 	purged, err := mset.purge(purgeRequest)
 	if err != nil {
-		resp.Error = NewJSStreamGeneralError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 	} else {
 		resp.Purged = purged
 		resp.Success = true
@@ -2559,19 +2559,19 @@ func (s *Server) jsStreamRestoreRequest(sub *subscription, c *client, _ *Account
 
 	var resp = JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	var req JSApiStreamRestoreRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -2588,14 +2588,14 @@ func (s *Server) jsStreamRestoreRequest(sub *subscription, c *client, _ *Account
 	}
 
 	if _, err := acc.lookupStream(stream); err == nil {
-		resp.Error = NewJSStreamNameExistError()
+		resp.Error = ApiErrors[JSStreamNameExistErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -2620,7 +2620,7 @@ func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamC
 
 	tfile, err := ioutil.TempFile(snapDir, "js-restore-")
 	if err != nil {
-		resp.Error = NewJSTempStorageFailedError()
+		resp.Error = ApiErrors[JSTempStorageFailedErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp))
 		return nil
 	}
@@ -2690,7 +2690,7 @@ func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamC
 		total += len(msg)
 		if js.wouldExceedLimits(FileStorage, total) {
 			s.resourcesExeededError()
-			resultCh <- result{NewJSInsufficientResourcesError(), reply}
+			resultCh <- result{ApiErrors[JSInsufficientResourcesErr], reply}
 			return
 		}
 
@@ -2712,7 +2712,7 @@ func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamC
 	if err != nil {
 		tfile.Close()
 		os.Remove(tfile.Name())
-		resp.Error = NewJSRestoreSubscribeFailedError(err, restoreSubj)
+		resp.Error = ApiErrors[JSRestoreSubscribeFailedErrF].NewT("{subject}", restoreSubj, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp))
 		return nil
 	}
@@ -2775,7 +2775,7 @@ func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamC
 				var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}
 
 				if err != nil {
-					resp.Error = NewJSStreamRestoreError(err, Unless(err))
+					resp.Error = ApiErrors[JSStreamRestoreErrF].ErrOrNewT(err, "{err}", err)
 					s.Warnf("Restore failed for %s for stream '%s > %s' in %v",
 						friendlyBytes(int64(total)), streamName, acc.Name, end.Sub(start))
 				} else {
@@ -2824,26 +2824,26 @@ func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Accoun
 
 	var resp = JSApiStreamSnapshotResponse{ApiResponse: ApiResponse{Type: JSApiStreamSnapshotResponseType}}
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		return
 	}
 	if isEmptyRequest(msg) {
-		resp.Error = NewJSBadRequestError()
+		resp.Error = ApiErrors[JSBadRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		return
 	}
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		return
 	}
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		}
 		return
@@ -2851,12 +2851,12 @@ func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Accoun
 
 	var req JSApiStreamSnapshotRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		return
 	}
 	if !IsValidSubject(req.DeliverSubject) {
-		resp.Error = NewJSSnapshotDeliverSubjectInvalidError()
+		resp.Error = ApiErrors[JSSnapshotDeliverSubjectInvalidErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 		return
 	}
@@ -2875,7 +2875,7 @@ func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Accoun
 		sr, err := mset.snapshot(0, req.CheckMsgs, !req.NoConsumers)
 		if err != nil {
 			s.Warnf("Snapshot of stream '%s > %s' failed: %v", mset.jsa.account.Name, mset.name(), err)
-			resp.Error = NewJSStreamSnapshotError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamSnapshotErrF].ErrOrNewT(err, "{err}", err)
 			s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
 			return
 		}
@@ -3040,7 +3040,7 @@ func (s *Server) jsConsumerCreate(sub *subscription, c *client, a *Account, subj
 
 	var req CreateConsumerRequest
 	if err := json.Unmarshal(msg, &req); err != nil {
-		resp.Error = NewJSInvalidJSONError()
+		resp.Error = ApiErrors[JSInvalidJSONErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -3058,7 +3058,7 @@ func (s *Server) jsConsumerCreate(sub *subscription, c *client, a *Account, subj
 				return
 			}
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				return
 			}
@@ -3071,43 +3071,43 @@ func (s *Server) jsConsumerCreate(sub *subscription, c *client, a *Account, subj
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if streamName != req.Stream {
-		resp.Error = NewJSStreamMismatchError()
+		resp.Error = ApiErrors[JSStreamMismatchErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	if expectDurable {
 		if numTokens(subject) != 7 {
-			resp.Error = NewJSConsumerDurableNameNotInSubjectError()
+			resp.Error = ApiErrors[JSConsumerDurableNameNotInSubjectErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		// Now check on requirements for durable request.
 		if req.Config.Durable == _EMPTY_ {
-			resp.Error = NewJSConsumerDurableNameNotSetError()
+			resp.Error = ApiErrors[JSConsumerDurableNameNotSetErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		consumerName := tokenAt(subject, 7)
 		if consumerName != req.Config.Durable {
-			resp.Error = NewJSConsumerDurableNameNotMatchSubjectError()
+			resp.Error = ApiErrors[JSConsumerDurableNameNotMatchSubjectErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 	} else {
 		if numTokens(subject) != 5 {
-			resp.Error = NewJSConsumerEphemeralWithDurableInSubjectError()
+			resp.Error = ApiErrors[JSConsumerEphemeralWithDurableInSubjectErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		if req.Config.Durable != _EMPTY_ {
-			resp.Error = NewJSConsumerEphemeralWithDurableNameError()
+			resp.Error = ApiErrors[JSConsumerEphemeralWithDurableNameErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3120,14 +3120,14 @@ func (s *Server) jsConsumerCreate(sub *subscription, c *client, a *Account, subj
 
 	stream, err := acc.lookupStream(req.Stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	o, err := stream.addConsumer(&req.Config)
 	if err != nil {
-		resp.Error = NewJSConsumerCreateError(err, Unless(err))
+		resp.Error = ApiErrors[JSConsumerCreateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -3158,7 +3158,7 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3170,7 +3170,7 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -3180,7 +3180,7 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account
 	if !isEmptyRequest(msg) {
 		var req JSApiConsumersRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3200,14 +3200,14 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account
 		sas := cc.streams[acc.Name]
 		if sas == nil {
 			js.mu.RUnlock()
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
 		sa := sas[streamName]
 		if sa == nil || sa.err != nil {
 			js.mu.RUnlock()
-			resp.Error = NewJSStreamNotFoundError()
+			resp.Error = ApiErrors[JSStreamNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3227,7 +3227,7 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account
 	} else {
 		mset, err := acc.lookupStream(streamName)
 		if err != nil {
-			resp.Error = NewJSStreamNotFoundError(Unless(err))
+			resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3279,7 +3279,7 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account,
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3291,7 +3291,7 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account,
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
@@ -3301,7 +3301,7 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account,
 	if !isEmptyRequest(msg) {
 		var req JSApiConsumersRequest
 		if err := json.Unmarshal(msg, &req); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3321,7 +3321,7 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account,
 
 	mset, err := acc.lookupStream(streamName)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -3385,23 +3385,23 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
 			// We can't find the consumer, so mimic what would be the errors below.
 			if hasJS, doErr := acc.checkJetStream(); !hasJS {
 				if doErr {
-					resp.Error = NewJSNotEnabledForAccountError()
+					resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				}
 				return
 			}
 			if sa == nil {
-				resp.Error = NewJSStreamNotFoundError()
+				resp.Error = ApiErrors[JSStreamNotFoundErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 				return
 			}
 			// If we are here the consumer is not present.
-			resp.Error = NewJSConsumerNotFoundError()
+			resp.Error = ApiErrors[JSConsumerNotFoundErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		} else if ca == nil {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				// Delaying an error response gives the leader a chance to respond before us
 				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
 			}
@@ -3410,7 +3410,7 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
 
 		// Check to see if we are a member of the group and if the group has no leader.
 		if js.isGroupLeaderless(ca.Group) {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3418,14 +3418,14 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
 		// We have the consumer assigned and a leader, so only the consumer leader should answer.
 		if !acc.JetStreamIsConsumerLeader(streamName, consumerName) {
 			if js.isLeaderless() {
-				resp.Error = NewJSClusterNotAvailError()
+				resp.Error = ApiErrors[JSClusterNotAvailErr]
 				// Delaying an error response gives the leader a chance to respond before us
 				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), ca.Group)
 			} else if ca != nil {
 				if rg := ca.Group; rg != nil && rg.node != nil && rg.isMember(ourID) {
 					// Check here if we are a member and this is just a new consumer that does not have a leader yet.
 					if rg.node.GroupLeader() == _EMPTY_ && !rg.node.HadPreviousLeader() {
-						resp.Error = NewJSConsumerNotFoundError()
+						resp.Error = ApiErrors[JSConsumerNotFoundErr]
 						s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
 					}
 				}
@@ -3435,26 +3435,26 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
 	}
 
 	if !acc.JetStreamEnabled() {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSNotEmptyRequestError()
+		resp.Error = ApiErrors[JSNotEmptyRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	mset, err := acc.lookupStream(streamName)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	obs := mset.lookupConsumer(consumerName)
 	if obs == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -3482,7 +3482,7 @@ func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, _ *Accoun
 			return
 		}
 		if js.isLeaderless() {
-			resp.Error = NewJSClusterNotAvailError()
+			resp.Error = ApiErrors[JSClusterNotAvailErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3494,13 +3494,13 @@ func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, _ *Accoun
 
 	if hasJS, doErr := acc.checkJetStream(); !hasJS {
 		if doErr {
-			resp.Error = NewJSNotEnabledForAccountError()
+			resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		}
 		return
 	}
 	if !isEmptyRequest(msg) {
-		resp.Error = NewJSNotEmptyRequestError()
+		resp.Error = ApiErrors[JSNotEmptyRequestErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
@@ -3514,19 +3514,19 @@ func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, _ *Accoun
 
 	mset, err := acc.lookupStream(stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 
 	obs := mset.lookupConsumer(consumer)
 	if obs == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
 	if err := obs.delete(); err != nil {
-		resp.Error = NewJSStreamGeneralError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 		return
 	}
diff --git a/server/jetstream_cluster.go b/server/jetstream_cluster.go
index 8234a8d8..96536aaa 100644
--- a/server/jetstream_cluster.go
+++ b/server/jetstream_cluster.go
@@ -205,7 +205,7 @@ func (s *Server) JetStreamIsCurrent() bool {
 func (s *Server) JetStreamSnapshotMeta() error {
 	js := s.getJetStream()
 	if js == nil {
-		return NewJSNotEnabledError()
+		return ApiErrors[JSNotEnabledErr]
 	}
 	js.mu.RLock()
 	cc := js.cluster
@@ -223,10 +223,10 @@ func (s *Server) JetStreamSnapshotMeta() error {
 func (s *Server) JetStreamStepdownStream(account, stream string) error {
 	js, cc := s.getJetStreamCluster()
 	if js == nil {
-		return NewJSNotEnabledError()
+		return ApiErrors[JSNotEnabledErr]
 	}
 	if cc == nil {
-		return NewJSClusterNotActiveError()
+		return ApiErrors[JSClusterNotActiveErr]
 	}
 	// Grab account
 	acc, err := s.LookupAccount(account)
@@ -249,10 +249,10 @@ func (s *Server) JetStreamStepdownStream(account, stream string) error {
 func (s *Server) JetStreamSnapshotStream(account, stream string) error {
 	js, cc := s.getJetStreamCluster()
 	if js == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 	if cc == nil {
-		return NewJSClusterNotActiveError()
+		return ApiErrors[JSClusterNotActiveErr]
 	}
 	// Grab account
 	acc, err := s.LookupAccount(account)
@@ -268,7 +268,7 @@ func (s *Server) JetStreamSnapshotStream(account, stream string) error {
 	mset.mu.RLock()
 	if !mset.node.Leader() {
 		mset.mu.RUnlock()
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 	n := mset.node
 	mset.mu.RUnlock()
@@ -436,7 +436,7 @@ func (s *Server) enableJetStreamClustering() error {
 	}
 	js := s.getJetStream()
 	if js == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 	// Already set.
 	if js.cluster != nil {
@@ -1192,7 +1192,7 @@ func (js *jetStream) createRaftGroup(rg *raftGroup, storage StorageType) error {
 	s, cc := js.srv, js.cluster
 
 	if cc == nil || cc.meta == nil {
-		return NewJSClusterNotActiveError()
+		return ApiErrors[JSClusterNotActiveErr]
 	}
 
 	// If this is a single peer raft group or we are not a member return.
@@ -1436,7 +1436,7 @@ func (js *jetStream) monitorStream(mset *stream, sa *streamAssignment) {
 					Stream:  sa.Config.Name,
 					Restore: &JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}},
 				}
-				result.Restore.Error = NewJSStreamAssignmentError(err, Unless(err))
+				result.Restore.Error = ApiErrors[JSStreamAssignmentErrF].ErrOrNewT(sa.err, "{err}", sa.err)
 				js.mu.Unlock()
 				// Send response to the metadata leader. They will forward to the user as needed.
 				s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result)
@@ -1535,6 +1535,24 @@ func (mset *stream) resetClusteredState() bool {
 	return true
 }
 
+func (mset *stream) checkForFlowControl(seq uint64) {
+	mset.mu.Lock()
+	if mset.fcr != nil {
+		if rply := mset.fcr[seq]; rply != _EMPTY_ {
+			delete(mset.fcr, seq)
+			mset.outq.send(&jsPubMsg{rply, _EMPTY_, _EMPTY_, nil, nil, nil, 0, nil})
+		} else if len(mset.fcr) > 0 {
+			for fseq, rply := range mset.fcr {
+				if fseq < seq {
+					delete(mset.fcr, fseq)
+					mset.outq.send(&jsPubMsg{rply, _EMPTY_, _EMPTY_, nil, nil, nil, 0, nil})
+				}
+			}
+		}
+	}
+	mset.mu.Unlock()
+}
+
 func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isRecovering bool) error {
 	for _, e := range ce.Entries {
 		if e.Type == EntryNormal {
@@ -1551,16 +1569,8 @@ func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isReco
 					panic(err.Error())
 				}
 
-				// Check for flowcontrol here.
-				if len(msg) == 0 && len(hdr) > 0 && reply != _EMPTY_ && bytes.HasPrefix(hdr, []byte("NATS/1.0 100 ")) {
-					mset.sendFlowControlReply(reply)
-					continue
-				}
-
-				// Grab last sequence.
-				last := mset.lastSeq()
-
 				// We can skip if we know this is less than what we already have.
+				last := mset.lastSeq()
 				if lseq < last {
 					s.Debugf("Apply stream entries skipping message with sequence %d with last of %d", lseq, last)
 					continue
@@ -1573,8 +1583,11 @@ func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isReco
 					continue
 				}
 
-				// Messages to be skipped have no subject or timestamp or msg or hdr.
-				if subject == _EMPTY_ && ts == 0 && len(msg) == 0 && len(hdr) == 0 {
+				// Check for flowcontrol here.
+				mset.checkForFlowControl(lseq + 1)
+
+				// Messages to be skipped have no subject or timestamp.
+				if subject == _EMPTY_ && ts == 0 {
 					// Skip and update our lseq.
 					mset.setLastSeq(mset.store.SkipMsg())
 					continue
@@ -1618,10 +1631,10 @@ func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isReco
 				if isLeader && !isRecovering {
 					var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}}
 					if err != nil {
-						resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err))
+						resp.Error = ApiErrors[JSStreamMsgDeleteFailedF].ErrOrNewT(err, "{err}", err)
 						s.sendAPIErrResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp))
 					} else if !removed {
-						resp.Error = NewJSSequenceNotFoundError(md.Seq)
+						resp.Error = ApiErrors[JSSequenceNotFoundErrF].NewT("{seq}", md.Seq)
 						s.sendAPIErrResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp))
 					} else {
 						resp.Success = true
@@ -1655,7 +1668,7 @@ func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isReco
 				if isLeader && !isRecovering {
 					var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}}
 					if err != nil {
-						resp.Error = NewJSStreamGeneralError(err, Unless(err))
+						resp.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 						s.sendAPIErrResponse(sp.Client, mset.account(), sp.Subject, sp.Reply, _EMPTY_, s.jsonResponse(resp))
 					} else {
 						resp.Purged = purged
@@ -1767,7 +1780,7 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) {
 	// Send our response.
 	var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}
 	if err != nil {
-		resp.Error = NewJSStreamCreateError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamCreateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp))
 	} else {
 		resp.StreamInfo = &StreamInfo{
@@ -1908,7 +1921,7 @@ func (js *jetStream) processStreamAssignment(sa *streamAssignment) bool {
 				Stream:   stream,
 				Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}},
 			}
-			result.Response.Error = NewJSNoAccountError()
+			result.Response.Error = ApiErrors[JSNoAccountErr]
 			s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result)
 			s.Warnf(ll)
 		} else {
@@ -2059,7 +2072,7 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, sa *streamAssignme
 			Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}},
 			Update:   true,
 		}
-		result.Response.Error = NewJSStreamGeneralError(err, Unless(err))
+		result.Response.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 		js.mu.Unlock()
 
 		// Send response to the metadata leader. They will forward to the user as needed.
@@ -2129,7 +2142,7 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme
 				s.Warnf("JetStream cluster error updating stream %q for account %q: %v", sa.Config.Name, acc.Name, err)
 				mset.setStreamAssignment(osa)
 			}
-		} else if err == NewJSStreamNotFoundError() {
+		} else if err == ApiErrors[JSStreamNotFoundErr] {
 			// Add in the stream here.
 			mset, err = acc.addStreamWithAssignment(sa.Config, nil, sa)
 		}
@@ -2162,7 +2175,7 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme
 				Stream:   sa.Config.Name,
 				Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}},
 			}
-			result.Response.Error = NewJSStreamCreateError(err, Unless(err))
+			result.Response.Error = ApiErrors[JSStreamCreateErrF].ErrOrNewT(err, "{err}", err)
 		}
 		js.mu.Unlock()
 
@@ -2206,7 +2219,7 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme
 							Stream:  sa.Config.Name,
 							Restore: &JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}},
 						}
-						result.Restore.Error = NewJSStreamRestoreError(err, Unless(err))
+						result.Restore.Error = ApiErrors[JSStreamRestoreErrF].ErrOrNewT(sa.err, "{err}", sa.err)
 						js.mu.Unlock()
 						// Send response to the metadata leader. They will forward to the user as needed.
 						b, _ := json.Marshal(result) // Avoids auto-processing and doing fancy json with newlines.
@@ -2319,7 +2332,7 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 	// Go ahead and delete the stream.
 	mset, err := acc.lookupStream(sa.Config.Name)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 	} else if mset != nil {
 		err = mset.stop(true, wasLeader)
 	}
@@ -2334,7 +2347,7 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 
 	if err != nil {
 		if resp.Error == nil {
-			resp.Error = NewJSStreamGeneralError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 		}
 		s.sendAPIErrResponse(sa.Client, acc, sa.Subject, sa.Reply, _EMPTY_, s.jsonResponse(resp))
 	} else {
@@ -2374,7 +2387,7 @@ func (js *jetStream) processConsumerAssignment(ca *consumerAssignment) {
 				Consumer: consumer,
 				Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
 			}
-			result.Response.Error = NewJSNoAccountError()
+			result.Response.Error = ApiErrors[JSNoAccountErr]
 			s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result)
 			s.Warnf(ll)
 		} else {
@@ -2480,14 +2493,14 @@ func (js *jetStream) processClusterCreateConsumer(ca *consumerAssignment, state
 	if err != nil {
 		js.mu.Lock()
 		s.Debugf("Consumer create failed, could not locate stream '%s > %s'", ca.Client.serviceAccount(), ca.Stream)
-		ca.err = NewJSStreamNotFoundError()
+		ca.err = ApiErrors[JSStreamNotFoundErr]
 		result := &consumerAssignmentResult{
 			Account:  ca.Client.serviceAccount(),
 			Stream:   ca.Stream,
 			Consumer: ca.Name,
 			Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
 		}
-		result.Response.Error = NewJSStreamNotFoundError()
+		result.Response.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result)
 		js.mu.Unlock()
 		return
@@ -2512,7 +2525,7 @@ func (js *jetStream) processClusterCreateConsumer(ca *consumerAssignment, state
 					Consumer: ca.Name,
 					Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
 				}
-				result.Response.Error = NewJSConsumerNameExistError()
+				result.Response.Error = ApiErrors[JSConsumerNameExistErr]
 				s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result)
 				js.mu.Unlock()
 				return
@@ -2559,7 +2572,7 @@ func (js *jetStream) processClusterCreateConsumer(ca *consumerAssignment, state
 				Consumer: ca.Name,
 				Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
 			}
-			result.Response.Error = NewJSConsumerCreateError(err, Unless(err))
+			result.Response.Error = ApiErrors[JSConsumerCreateErrF].ErrOrNewT(err, "{err}", err)
 		} else if err == errNoInterest {
 			// This is a stranded ephemeral, let's clean this one up.
 			subject := fmt.Sprintf(JSApiConsumerDeleteT, ca.Stream, ca.Name)
@@ -2605,12 +2618,12 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 	// Go ahead and delete the consumer.
 	mset, err := acc.lookupStream(ca.Stream)
 	if err != nil {
-		resp.Error = NewJSStreamNotFoundError(Unless(err))
+		resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 	} else if mset != nil {
 		if o := mset.lookupConsumer(ca.Name); o != nil {
 			err = o.stopWithFlags(true, false, true, wasLeader)
 		} else {
-			resp.Error = NewJSConsumerNotFoundError()
+			resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		}
 	}
 
@@ -2624,7 +2637,7 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 
 	if err != nil {
 		if resp.Error == nil {
-			resp.Error = NewJSStreamNotFoundError(Unless(err))
+			resp.Error = ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 		}
 		s.sendAPIErrResponse(ca.Client, acc, ca.Subject, ca.Reply, _EMPTY_, s.jsonResponse(resp))
 	} else {
@@ -2958,7 +2971,7 @@ func (js *jetStream) processConsumerLeaderChange(o *consumer, isLeader bool) {
 
 	var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}
 	if err != nil {
-		resp.Error = NewJSConsumerCreateError(err, Unless(err))
+		resp.Error = ApiErrors[JSConsumerCreateErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp))
 	} else {
 		resp.ConsumerInfo = o.info()
@@ -3092,7 +3105,7 @@ func (js *jetStream) processStreamAssignmentResults(sub *subscription, c *client
 		// TODO(dlc) - Could have mixed results, should track per peer.
 		// Set sa.err while we are deleting so we will not respond to list/names requests.
 		if !result.Update && time.Since(sa.Created) < 5*time.Second {
-			sa.err = NewJSClusterNotAssignedError()
+			sa.err = ApiErrors[JSClusterNotAssignedErr]
 			cc.meta.Propose(encodeDeleteStreamAssignment(sa))
 		}
 	}
@@ -3123,7 +3136,7 @@ func (js *jetStream) processConsumerAssignmentResults(sub *subscription, c *clie
 			// TODO(dlc) - Could have mixed results, should track per peer.
 			if result.Response.Error != nil {
 				// So while we are deleting we will not respond to list/names requests.
-				ca.err = NewJSClusterNotAssignedError()
+				ca.err = ApiErrors[JSClusterNotAssignedErr]
 				cc.meta.Propose(encodeDeleteConsumerAssignment(ca))
 			}
 		}
@@ -3309,14 +3322,14 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 	acc.mu.RUnlock()
 
 	if jsa == nil {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 
 	ccfg, err := checkStreamCfg(config)
 	if err != nil {
-		resp.Error = NewJSStreamInvalidConfigError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamInvalidConfigF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3333,14 +3346,14 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 	jsa.mu.RUnlock()
 
 	if exceeded {
-		resp.Error = NewJSMaximumStreamsLimitError()
+		resp.Error = ApiErrors[JSMaximumStreamsLimitErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Check for stream limits here before proposing.
 	if err := jsa.checkLimits(cfg); err != nil {
-		resp.Error = NewJSStreamLimitsError(err, Unless(err))
+		resp.Error = ApiErrors[JSStreamLimitsErrF].ErrOrNewT(err, "{err}", err)
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3350,7 +3363,7 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 	defer js.mu.Unlock()
 
 	if sa := js.streamAssignment(acc.Name, cfg.Name); sa != nil {
-		resp.Error = NewJSStreamNameExistError()
+		resp.Error = ApiErrors[JSStreamNameExistErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3360,7 +3373,7 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 		for _, subj := range sa.Config.Subjects {
 			for _, tsubj := range cfg.Subjects {
 				if SubjectsCollide(tsubj, subj) {
-					resp.Error = NewJSStreamSubjectOverlapError()
+					resp.Error = ApiErrors[JSStreamSubjectOverlapErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 					return
 				}
@@ -3371,7 +3384,7 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 	// Raft group selection and placement.
 	rg := cc.createGroupForStream(ci, cfg)
 	if rg == nil {
-		resp.Error = NewJSInsufficientResourcesError()
+		resp.Error = ApiErrors[JSInsufficientResourcesErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3397,32 +3410,32 @@ func (s *Server) jsClusteredStreamUpdateRequest(ci *ClientInfo, acc *Account, su
 	osa := js.streamAssignment(acc.Name, cfg.Name)
 
 	if osa == nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 	var newCfg *StreamConfig
 	if jsa := js.accounts[acc.Name]; jsa != nil {
 		if ncfg, err := jsa.configUpdateCheck(osa.Config, cfg); err != nil {
-			resp.Error = NewJSStreamUpdateError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamUpdateErrF].ErrOrNewT(err, "{err}", err)
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 			return
 		} else {
 			newCfg = ncfg
 		}
 	} else {
-		resp.Error = NewJSNotEnabledForAccountError()
+		resp.Error = ApiErrors[JSNotEnabledForAccountErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 	// Check for cluster changes that we want to error on.
 	if newCfg.Replicas != len(osa.Group.Peers) {
-		resp.Error = NewJSStreamReplicasNotUpdatableError()
+		resp.Error = ApiErrors[JSStreamReplicasNotUpdatableErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 	if !reflect.DeepEqual(newCfg.Mirror, osa.Config.Mirror) {
-		resp.Error = NewJSStreamMirrorNotUpdatableError()
+		resp.Error = ApiErrors[JSStreamMirrorNotUpdatableErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3435,7 +3448,7 @@ func (s *Server) jsClusteredStreamUpdateRequest(ci *ClientInfo, acc *Account, su
 		for _, subj := range sa.Config.Subjects {
 			for _, tsubj := range newCfg.Subjects {
 				if SubjectsCollide(tsubj, subj) {
-					resp.Error = NewJSStreamSubjectOverlapError()
+					resp.Error = ApiErrors[JSStreamSubjectOverlapErr]
 					s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 					return
 				}
@@ -3459,7 +3472,7 @@ func (s *Server) jsClusteredStreamDeleteRequest(ci *ClientInfo, acc *Account, st
 	osa := js.streamAssignment(acc.Name, stream)
 	if osa == nil {
 		var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}}
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3494,7 +3507,7 @@ func (s *Server) jsClusteredStreamPurgeRequest(
 	sa := js.streamAssignment(acc.Name, stream)
 	if sa == nil {
 		resp := JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}}
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3506,7 +3519,7 @@ func (s *Server) jsClusteredStreamPurgeRequest(
 		var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}}
 		purged, err := mset.purge(preq)
 		if err != nil {
-			resp.Error = NewJSStreamGeneralError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamGeneralErrorF].ErrOrNewT(err, "{err}", err)
 		} else {
 			resp.Purged = purged
 			resp.Success = true
@@ -3528,7 +3541,7 @@ func (s *Server) jsClusteredStreamRestoreRequest(ci *ClientInfo, acc *Account, r
 	resp := JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}
 
 	if sa := js.streamAssignment(ci.serviceAccount(), cfg.Name); sa != nil {
-		resp.Error = NewJSStreamNameExistError()
+		resp.Error = ApiErrors[JSStreamNameExistErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3536,7 +3549,7 @@ func (s *Server) jsClusteredStreamRestoreRequest(ci *ClientInfo, acc *Account, r
 	// Raft group selection and placement.
 	rg := cc.createGroupForStream(ci, cfg)
 	if rg == nil {
-		resp.Error = NewJSInsufficientResourcesError()
+		resp.Error = ApiErrors[JSInsufficientResourcesErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3664,7 +3677,7 @@ LOOP:
 			return
 		case <-notActive.C:
 			s.Warnf("Did not receive all stream info results for %q", acc)
-			resp.Error = NewJSClusterIncompleteError()
+			resp.Error = ApiErrors[JSClusterIncompleteErr]
 			break LOOP
 		case si := <-rc:
 			resp.Streams = append(resp.Streams, si)
@@ -3842,19 +3855,19 @@ func (s *Server) jsClusteredConsumerDeleteRequest(ci *ClientInfo, acc *Account,
 
 	sa := js.streamAssignment(acc.Name, stream)
 	if sa == nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 
 	}
 	if sa.consumers == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 	oca := sa.consumers[consumer]
 	if oca == nil {
-		resp.Error = NewJSConsumerNotFoundError()
+		resp.Error = ApiErrors[JSConsumerNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3904,9 +3917,9 @@ func (s *Server) jsClusteredMsgDeleteRequest(ci *ClientInfo, acc *Account, mset
 		}
 		var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}}
 		if err != nil {
-			resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamMsgDeleteFailedF].ErrOrNewT(err, "{err}", err)
 		} else if !removed {
-			resp.Error = NewJSSequenceNotFoundError(req.Seq)
+			resp.Error = ApiErrors[JSSequenceNotFoundErrF].NewT("{seq}", req.Seq)
 		} else {
 			resp.Success = true
 		}
@@ -3965,14 +3978,14 @@ func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subjec
 	// Lookup the stream assignment.
 	sa := js.streamAssignment(acc.Name, stream)
 	if sa == nil {
-		resp.Error = NewJSStreamNotFoundError()
+		resp.Error = ApiErrors[JSStreamNotFoundErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
 
 	// Check for max consumers here to short circuit if possible.
 	if maxc := sa.Config.MaxConsumers; maxc > 0 && len(sa.consumers) >= maxc {
-		resp.Error = NewJSMaximumConsumersLimitError()
+		resp.Error = ApiErrors[JSMaximumConsumersLimitErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -3987,7 +4000,8 @@ func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subjec
 			}
 		}
 		if badConfig {
-			resp.Error = NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but FilterSubject is not set"))
+			resp.Error = ApiErrors[JSConsumerInvalidPolicyErrF].NewT("{err}",
+				"consumer delivery policy is deliver last per subject, but FilterSubject is not set")
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 			return
 		}
@@ -4008,7 +4022,7 @@ func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subjec
 
 	rg := cc.createGroupForConsumer(sa)
 	if rg == nil {
-		resp.Error = NewJSInsufficientResourcesError()
+		resp.Error = ApiErrors[JSInsufficientResourcesErr]
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -4043,7 +4057,7 @@ func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subjec
 				shouldErr = len(rr.psubs)+len(rr.qsubs) != 0
 			}
 			if shouldErr {
-				resp.Error = NewJSConsumerNameExistError()
+				resp.Error = ApiErrors[JSConsumerNameExistErr]
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 				return
 			}
@@ -4142,9 +4156,7 @@ func decodeStreamMsg(buf []byte) (subject, reply string, hdr, msg []byte, lseq u
 	if len(buf) < hl {
 		return _EMPTY_, _EMPTY_, nil, nil, 0, 0, errBadStreamMsg
 	}
-	if hdr = buf[:hl]; len(hdr) == 0 {
-		hdr = nil
-	}
+	hdr = buf[:hl]
 	buf = buf[hl:]
 	if len(buf) < 4 {
 		return _EMPTY_, _EMPTY_, nil, nil, 0, 0, errBadStreamMsg
@@ -4154,9 +4166,7 @@ func decodeStreamMsg(buf []byte) (subject, reply string, hdr, msg []byte, lseq u
 	if len(buf) < ml {
 		return _EMPTY_, _EMPTY_, nil, nil, 0, 0, errBadStreamMsg
 	}
-	if msg = buf[:ml]; len(msg) == 0 {
-		msg = nil
-	}
+	msg = buf[:ml]
 	return subject, reply, hdr, msg, lseq, ts, nil
 }
 
@@ -4222,7 +4232,7 @@ func (mset *stream) stateSnapshot() []byte {
 }
 
 // processClusteredMsg will propose the inbound message to the underlying raft group.
-func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg []byte) error {
+func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg []byte) (uint64, error) {
 	// For possible error response.
 	var response []byte
 
@@ -4239,14 +4249,14 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 	if js.limitsExceeded(stype) {
 		s.resourcesExeededError()
 		if canRespond {
-			b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: name}, Error: NewJSInsufficientResourcesError()})
+			b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: name}, Error: ApiErrors[JSInsufficientResourcesErr]})
 			outq.send(&jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, b, nil, 0, nil})
 		}
 		// Stepdown regardless.
 		if node := mset.raftNode(); node != nil {
 			node.StepDown()
 		}
-		return NewJSInsufficientResourcesError()
+		return 0, ApiErrors[JSInsufficientResourcesErr]
 	}
 
 	// Check here pre-emptively if we have exceeded our account limits.
@@ -4271,11 +4281,11 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 		s.Warnf(err.Error())
 		if canRespond {
 			var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}
-			resp.Error = NewJSAccountResourcesExceededError()
+			resp.Error = ApiErrors[JSAccountResourcesExceededErr]
 			response, _ = json.Marshal(resp)
 			outq.send(&jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, response, nil, 0, nil})
 		}
-		return err
+		return 0, err
 	}
 
 	// Check msgSize if we have a limit set there. Again this works if it goes through but better to be pre-emptive.
@@ -4284,11 +4294,11 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 		s.Warnf(err.Error())
 		if canRespond {
 			var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}
-			resp.Error = NewJSStreamMessageExceedsMaximumError()
+			resp.Error = ApiErrors[JSStreamMessageExceedsMaximumErr]
 			response, _ = json.Marshal(resp)
 			outq.send(&jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, response, nil, 0, nil})
 		}
-		return err
+		return 0, err
 	}
 
 	// Proceed with proposing this message.
@@ -4297,11 +4307,14 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 	// Check if we need to set initial value here
 	mset.clMu.Lock()
 	if mset.clseq == 0 || mset.clseq < lseq {
-		mset.clseq = mset.lastSeq()
+		mset.mu.RLock()
+		mset.clseq = mset.lseq
+		mset.mu.RUnlock()
 	}
 
 	esm := encodeStreamMsg(subject, reply, hdr, msg, mset.clseq, time.Now().UnixNano())
 	mset.clseq++
+	seq := mset.clseq
 
 	// Do proposal.
 	err := mset.node.Propose(esm)
@@ -4311,6 +4324,7 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 	mset.clMu.Unlock()
 
 	if err != nil {
+		seq = 0
 		if canRespond {
 			var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: mset.cfg.Name}}
 			resp.Error = &ApiError{Code: 503, Description: err.Error()}
@@ -4324,7 +4338,7 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [
 		s.handleOutOfSpace(msetName)
 	}
 
-	return err
+	return seq, err
 }
 
 // For requesting messages post raft snapshot to catch up streams post server restart.
@@ -4553,7 +4567,7 @@ RETRY:
 			} else if isOutOfSpaceErr(err) {
 				s.handleOutOfSpace(msetName)
 				return
-			} else if err == NewJSInsufficientResourcesError() {
+			} else if err == ApiErrors[JSInsufficientResourcesErr] {
 				s.resourcesExeededError()
 				return
 			} else {
@@ -4589,7 +4603,7 @@ func (mset *stream) processCatchupMsg(msg []byte) (uint64, error) {
 	}
 
 	if mset.js.limitsExceeded(mset.cfg.Storage) {
-		return 0, NewJSInsufficientResourcesError()
+		return 0, ApiErrors[JSInsufficientResourcesErr]
 	}
 
 	// Put into our store
diff --git a/server/jetstream_errors.go b/server/jetstream_errors.go
index 215fdd2f..b00dca75 100644
--- a/server/jetstream_errors.go
+++ b/server/jetstream_errors.go
@@ -2,30 +2,9 @@ package server
 
 import (
 	"fmt"
+	"strings"
 )
 
-type errOpts struct {
-	err error
-}
-
-// ErrorOption configures a NATS Error helper
-type ErrorOption func(*errOpts)
-
-// Unless ensures that if err is a ApiErr that err will be returned rather than the one being created via the helper
-func Unless(err error) ErrorOption {
-	return func(opts *errOpts) {
-		opts.err = err
-	}
-}
-
-func parseOpts(opts []ErrorOption) *errOpts {
-	eopts := &errOpts{}
-	for _, opt := range opts {
-		opt(eopts)
-	}
-	return eopts
-}
-
 type ErrorIdentifier uint16
 
 // IsNatsErr determines if a error matches ID, if multiple IDs are given if the error matches any of these the function will be true
@@ -76,12 +55,43 @@ func (e *ApiError) Error() string {
 	return fmt.Sprintf("%s (%d)", e.Description, e.ErrCode)
 }
 
-func (e *ApiError) toReplacerArgs(replacements []interface{}) []string {
-	var (
-		ra  []string
-		key string
-	)
+// ErrOrNewT returns err if it's an ApiError else creates a new error using NewT()
+func (e *ApiError) ErrOrNewT(err error, replacements ...interface{}) *ApiError {
+	if ae, ok := err.(*ApiError); ok {
+		return ae
+	}
+
+	return e.NewT(replacements...)
+}
+
+// ErrOr returns err if it's an ApiError else creates a new error
+func (e *ApiError) ErrOr(err error) *ApiError {
+	if ae, ok := err.(*ApiError); ok {
+		return ae
+	}
+
+	return e
+}
+
+// NewT creates a new error using strings.Replacer on the Description field, arguments must be an even number like NewT("{err}", err)
+func (e *ApiError) NewT(replacements ...interface{}) *ApiError {
+	ne := &ApiError{
+		Code:        e.Code,
+		ErrCode:     e.ErrCode,
+		Description: e.Description,
+	}
+
+	if len(replacements) == 0 {
+		return ne
+	}
+
+	if len(replacements)%2 != 0 {
+		panic("invalid error replacement")
+	}
+
+	var ra []string
 
+	var key string
 	for i, replacement := range replacements {
 		if i%2 == 0 {
 			key = replacement.(string)
@@ -98,5 +108,7 @@ func (e *ApiError) toReplacerArgs(replacements []interface{}) []string {
 		}
 	}
 
-	return ra
+	ne.Description = strings.NewReplacer(ra...).Replace(e.Description)
+
+	return ne
 }
diff --git a/server/jetstream_errors_generated.go b/server/jetstream_errors_generated.go
index d259a68e..2c2628f9 100644
--- a/server/jetstream_errors_generated.go
+++ b/server/jetstream_errors_generated.go
@@ -2,8 +2,6 @@
 
 package server
 
-import "strings"
-
 const (
 	// JSAccountResourcesExceededErr resource limits exceeded for account
 	JSAccountResourcesExceededErr ErrorIdentifier = 10002
@@ -452,1227 +450,3 @@ var (
 	// ErrReplicasNotSupported Deprecated by JSStreamReplicasNotSupportedErr ApiError, use IsNatsError() for comparisons
 	ErrReplicasNotSupported = ApiErrors[JSStreamReplicasNotSupportedErr]
 )
-
-// NewJSAccountResourcesExceededError creates a new JSAccountResourcesExceededErr error: "resource limits exceeded for account"
-func NewJSAccountResourcesExceededError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSAccountResourcesExceededErr]
-}
-
-// NewJSBadRequestError creates a new JSBadRequestErr error: "bad request"
-func NewJSBadRequestError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSBadRequestErr]
-}
-
-// NewJSClusterIncompleteError creates a new JSClusterIncompleteErr error: "incomplete results"
-func NewJSClusterIncompleteError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterIncompleteErr]
-}
-
-// NewJSClusterNoPeersError creates a new JSClusterNoPeersErr error: "no suitable peers for placement"
-func NewJSClusterNoPeersError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterNoPeersErr]
-}
-
-// NewJSClusterNotActiveError creates a new JSClusterNotActiveErr error: "JetStream not in clustered mode"
-func NewJSClusterNotActiveError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterNotActiveErr]
-}
-
-// NewJSClusterNotAssignedError creates a new JSClusterNotAssignedErr error: "JetStream cluster not assigned to this server"
-func NewJSClusterNotAssignedError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterNotAssignedErr]
-}
-
-// NewJSClusterNotAvailError creates a new JSClusterNotAvailErr error: "JetStream system temporarily unavailable"
-func NewJSClusterNotAvailError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterNotAvailErr]
-}
-
-// NewJSClusterNotLeaderError creates a new JSClusterNotLeaderErr error: "JetStream cluster can not handle request"
-func NewJSClusterNotLeaderError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterNotLeaderErr]
-}
-
-// NewJSClusterPeerNotMemberError creates a new JSClusterPeerNotMemberErr error: "peer not a member"
-func NewJSClusterPeerNotMemberError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterPeerNotMemberErr]
-}
-
-// NewJSClusterRequiredError creates a new JSClusterRequiredErr error: "JetStream clustering support required"
-func NewJSClusterRequiredError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterRequiredErr]
-}
-
-// NewJSClusterServerNotMemberError creates a new JSClusterServerNotMemberErr error: "server is not a member of the cluster"
-func NewJSClusterServerNotMemberError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterServerNotMemberErr]
-}
-
-// NewJSClusterTagsError creates a new JSClusterTagsErr error: "tags placement not supported for operation"
-func NewJSClusterTagsError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterTagsErr]
-}
-
-// NewJSClusterUnSupportFeatureError creates a new JSClusterUnSupportFeatureErr error: "not currently supported in clustered mode"
-func NewJSClusterUnSupportFeatureError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSClusterUnSupportFeatureErr]
-}
-
-// NewJSConsumerBadDurableNameError creates a new JSConsumerBadDurableNameErr error: "durable name can not contain '.', '*', '>'"
-func NewJSConsumerBadDurableNameError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerBadDurableNameErr]
-}
-
-// NewJSConsumerConfigRequiredError creates a new JSConsumerConfigRequiredErr error: "consumer config required"
-func NewJSConsumerConfigRequiredError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerConfigRequiredErr]
-}
-
-// NewJSConsumerCreateError creates a new JSConsumerCreateErrF error: "{err}"
-func NewJSConsumerCreateError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerCreateErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerDeliverCycleError creates a new JSConsumerDeliverCycleErr error: "consumer deliver subject forms a cycle"
-func NewJSConsumerDeliverCycleError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDeliverCycleErr]
-}
-
-// NewJSConsumerDeliverToWildcardsError creates a new JSConsumerDeliverToWildcardsErr error: "consumer deliver subject has wildcards"
-func NewJSConsumerDeliverToWildcardsError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDeliverToWildcardsErr]
-}
-
-// NewJSConsumerDescriptionTooLongError creates a new JSConsumerDescriptionTooLongErrF error: "consumer description is too long, maximum allowed is {max}"
-func NewJSConsumerDescriptionTooLongError(max interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerDescriptionTooLongErrF]
-	args := e.toReplacerArgs([]interface{}{"{max}", max})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerDirectRequiresEphemeralError creates a new JSConsumerDirectRequiresEphemeralErr error: "consumer direct requires an ephemeral consumer"
-func NewJSConsumerDirectRequiresEphemeralError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDirectRequiresEphemeralErr]
-}
-
-// NewJSConsumerDirectRequiresPushError creates a new JSConsumerDirectRequiresPushErr error: "consumer direct requires a push based consumer"
-func NewJSConsumerDirectRequiresPushError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDirectRequiresPushErr]
-}
-
-// NewJSConsumerDurableNameNotInSubjectError creates a new JSConsumerDurableNameNotInSubjectErr error: "consumer expected to be durable but no durable name set in subject"
-func NewJSConsumerDurableNameNotInSubjectError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDurableNameNotInSubjectErr]
-}
-
-// NewJSConsumerDurableNameNotMatchSubjectError creates a new JSConsumerDurableNameNotMatchSubjectErr error: "consumer name in subject does not match durable name in request"
-func NewJSConsumerDurableNameNotMatchSubjectError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDurableNameNotMatchSubjectErr]
-}
-
-// NewJSConsumerDurableNameNotSetError creates a new JSConsumerDurableNameNotSetErr error: "consumer expected to be durable but a durable name was not set"
-func NewJSConsumerDurableNameNotSetError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerDurableNameNotSetErr]
-}
-
-// NewJSConsumerEphemeralWithDurableInSubjectError creates a new JSConsumerEphemeralWithDurableInSubjectErr error: "consumer expected to be ephemeral but detected a durable name set in subject"
-func NewJSConsumerEphemeralWithDurableInSubjectError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerEphemeralWithDurableInSubjectErr]
-}
-
-// NewJSConsumerEphemeralWithDurableNameError creates a new JSConsumerEphemeralWithDurableNameErr error: "consumer expected to be ephemeral but a durable name was set in request"
-func NewJSConsumerEphemeralWithDurableNameError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerEphemeralWithDurableNameErr]
-}
-
-// NewJSConsumerExistingActiveError creates a new JSConsumerExistingActiveErr error: "consumer already exists and is still active"
-func NewJSConsumerExistingActiveError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerExistingActiveErr]
-}
-
-// NewJSConsumerFCRequiresPushError creates a new JSConsumerFCRequiresPushErr error: "consumer flow control requires a push based consumer"
-func NewJSConsumerFCRequiresPushError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerFCRequiresPushErr]
-}
-
-// NewJSConsumerFilterNotSubsetError creates a new JSConsumerFilterNotSubsetErr error: "consumer filter subject is not a valid subset of the interest subjects"
-func NewJSConsumerFilterNotSubsetError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerFilterNotSubsetErr]
-}
-
-// NewJSConsumerHBRequiresPushError creates a new JSConsumerHBRequiresPushErr error: "consumer idle heartbeat requires a push based consumer"
-func NewJSConsumerHBRequiresPushError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerHBRequiresPushErr]
-}
-
-// NewJSConsumerInvalidPolicyError creates a new JSConsumerInvalidPolicyErrF error: "{err}"
-func NewJSConsumerInvalidPolicyError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerInvalidPolicyErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerInvalidSamplingError creates a new JSConsumerInvalidSamplingErrF error: "failed to parse consumer sampling configuration: {err}"
-func NewJSConsumerInvalidSamplingError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerInvalidSamplingErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerMaxPendingAckPolicyRequiredError creates a new JSConsumerMaxPendingAckPolicyRequiredErr error: "consumer requires ack policy for max ack pending"
-func NewJSConsumerMaxPendingAckPolicyRequiredError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerMaxPendingAckPolicyRequiredErr]
-}
-
-// NewJSConsumerMaxWaitingNegativeError creates a new JSConsumerMaxWaitingNegativeErr error: "consumer max waiting needs to be positive"
-func NewJSConsumerMaxWaitingNegativeError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerMaxWaitingNegativeErr]
-}
-
-// NewJSConsumerNameExistError creates a new JSConsumerNameExistErr error: "consumer name already in use"
-func NewJSConsumerNameExistError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerNameExistErr]
-}
-
-// NewJSConsumerNameTooLongError creates a new JSConsumerNameTooLongErrF error: "consumer name is too long, maximum allowed is {max}"
-func NewJSConsumerNameTooLongError(max interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerNameTooLongErrF]
-	args := e.toReplacerArgs([]interface{}{"{max}", max})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerNotFoundError creates a new JSConsumerNotFoundErr error: "consumer not found"
-func NewJSConsumerNotFoundError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerNotFoundErr]
-}
-
-// NewJSConsumerOnMappedError creates a new JSConsumerOnMappedErr error: "consumer direct on a mapped consumer"
-func NewJSConsumerOnMappedError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerOnMappedErr]
-}
-
-// NewJSConsumerPullNotDurableError creates a new JSConsumerPullNotDurableErr error: "consumer in pull mode requires a durable name"
-func NewJSConsumerPullNotDurableError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerPullNotDurableErr]
-}
-
-// NewJSConsumerPullRequiresAckError creates a new JSConsumerPullRequiresAckErr error: "consumer in pull mode requires explicit ack policy"
-func NewJSConsumerPullRequiresAckError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerPullRequiresAckErr]
-}
-
-// NewJSConsumerPullWithRateLimitError creates a new JSConsumerPullWithRateLimitErr error: "consumer in pull mode can not have rate limit set"
-func NewJSConsumerPullWithRateLimitError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerPullWithRateLimitErr]
-}
-
-// NewJSConsumerPushMaxWaitingError creates a new JSConsumerPushMaxWaitingErr error: "consumer in push mode can not set max waiting"
-func NewJSConsumerPushMaxWaitingError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerPushMaxWaitingErr]
-}
-
-// NewJSConsumerReplacementWithDifferentNameError creates a new JSConsumerReplacementWithDifferentNameErr error: "consumer replacement durable config not the same"
-func NewJSConsumerReplacementWithDifferentNameError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerReplacementWithDifferentNameErr]
-}
-
-// NewJSConsumerSmallHeartbeatError creates a new JSConsumerSmallHeartbeatErr error: "consumer idle heartbeat needs to be >= 100ms"
-func NewJSConsumerSmallHeartbeatError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerSmallHeartbeatErr]
-}
-
-// NewJSConsumerStoreFailedError creates a new JSConsumerStoreFailedErrF error: "error creating store for consumer: {err}"
-func NewJSConsumerStoreFailedError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSConsumerStoreFailedErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSConsumerWQConsumerNotDeliverAllError creates a new JSConsumerWQConsumerNotDeliverAllErr error: "consumer must be deliver all on workqueue stream"
-func NewJSConsumerWQConsumerNotDeliverAllError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerWQConsumerNotDeliverAllErr]
-}
-
-// NewJSConsumerWQConsumerNotUniqueError creates a new JSConsumerWQConsumerNotUniqueErr error: "filtered consumer not unique on workqueue stream"
-func NewJSConsumerWQConsumerNotUniqueError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerWQConsumerNotUniqueErr]
-}
-
-// NewJSConsumerWQMultipleUnfilteredError creates a new JSConsumerWQMultipleUnfilteredErr error: "multiple non-filtered consumers not allowed on workqueue stream"
-func NewJSConsumerWQMultipleUnfilteredError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerWQMultipleUnfilteredErr]
-}
-
-// NewJSConsumerWQRequiresExplicitAckError creates a new JSConsumerWQRequiresExplicitAckErr error: "workqueue stream requires explicit ack"
-func NewJSConsumerWQRequiresExplicitAckError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSConsumerWQRequiresExplicitAckErr]
-}
-
-// NewJSInsufficientResourcesError creates a new JSInsufficientResourcesErr error: "insufficient resources"
-func NewJSInsufficientResourcesError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSInsufficientResourcesErr]
-}
-
-// NewJSInvalidJSONError creates a new JSInvalidJSONErr error: "invalid JSON"
-func NewJSInvalidJSONError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSInvalidJSONErr]
-}
-
-// NewJSMaximumConsumersLimitError creates a new JSMaximumConsumersLimitErr error: "maximum consumers limit reached"
-func NewJSMaximumConsumersLimitError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMaximumConsumersLimitErr]
-}
-
-// NewJSMaximumStreamsLimitError creates a new JSMaximumStreamsLimitErr error: "maximum number of streams reached"
-func NewJSMaximumStreamsLimitError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMaximumStreamsLimitErr]
-}
-
-// NewJSMemoryResourcesExceededError creates a new JSMemoryResourcesExceededErr error: "insufficient memory resources available"
-func NewJSMemoryResourcesExceededError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMemoryResourcesExceededErr]
-}
-
-// NewJSMirrorConsumerSetupFailedError creates a new JSMirrorConsumerSetupFailedErrF error: "{err}"
-func NewJSMirrorConsumerSetupFailedError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSMirrorConsumerSetupFailedErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSMirrorMaxMessageSizeTooBigError creates a new JSMirrorMaxMessageSizeTooBigErr error: "stream mirror must have max message size >= source"
-func NewJSMirrorMaxMessageSizeTooBigError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMirrorMaxMessageSizeTooBigErr]
-}
-
-// NewJSMirrorWithSourcesError creates a new JSMirrorWithSourcesErr error: "stream mirrors can not also contain other sources"
-func NewJSMirrorWithSourcesError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMirrorWithSourcesErr]
-}
-
-// NewJSMirrorWithStartSeqAndTimeError creates a new JSMirrorWithStartSeqAndTimeErr error: "stream mirrors can not have both start seq and start time configured"
-func NewJSMirrorWithStartSeqAndTimeError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMirrorWithStartSeqAndTimeErr]
-}
-
-// NewJSMirrorWithSubjectFiltersError creates a new JSMirrorWithSubjectFiltersErr error: "stream mirrors can not contain filtered subjects"
-func NewJSMirrorWithSubjectFiltersError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMirrorWithSubjectFiltersErr]
-}
-
-// NewJSMirrorWithSubjectsError creates a new JSMirrorWithSubjectsErr error: "stream mirrors can not also contain subjects"
-func NewJSMirrorWithSubjectsError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSMirrorWithSubjectsErr]
-}
-
-// NewJSNoAccountError creates a new JSNoAccountErr error: "account not found"
-func NewJSNoAccountError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSNoAccountErr]
-}
-
-// NewJSNoMessageFoundError creates a new JSNoMessageFoundErr error: "no message found"
-func NewJSNoMessageFoundError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSNoMessageFoundErr]
-}
-
-// NewJSNotEmptyRequestError creates a new JSNotEmptyRequestErr error: "expected an empty request payload"
-func NewJSNotEmptyRequestError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSNotEmptyRequestErr]
-}
-
-// NewJSNotEnabledError creates a new JSNotEnabledErr error: "JetStream not enabled"
-func NewJSNotEnabledError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSNotEnabledErr]
-}
-
-// NewJSNotEnabledForAccountError creates a new JSNotEnabledForAccountErr error: "JetStream not enabled for account"
-func NewJSNotEnabledForAccountError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSNotEnabledForAccountErr]
-}
-
-// NewJSPeerRemapError creates a new JSPeerRemapErr error: "peer remap failed"
-func NewJSPeerRemapError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSPeerRemapErr]
-}
-
-// NewJSRaftGeneralError creates a new JSRaftGeneralErrF error: "{err}"
-func NewJSRaftGeneralError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSRaftGeneralErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSRestoreSubscribeFailedError creates a new JSRestoreSubscribeFailedErrF error: "JetStream unable to subscribe to restore snapshot {subject}: {err}"
-func NewJSRestoreSubscribeFailedError(err error, subject interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSRestoreSubscribeFailedErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err, "{subject}", subject})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSSequenceNotFoundError creates a new JSSequenceNotFoundErrF error: "sequence {seq} not found"
-func NewJSSequenceNotFoundError(seq uint64, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSSequenceNotFoundErrF]
-	args := e.toReplacerArgs([]interface{}{"{seq}", seq})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSSnapshotDeliverSubjectInvalidError creates a new JSSnapshotDeliverSubjectInvalidErr error: "deliver subject not valid"
-func NewJSSnapshotDeliverSubjectInvalidError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSSnapshotDeliverSubjectInvalidErr]
-}
-
-// NewJSSourceConsumerSetupFailedError creates a new JSSourceConsumerSetupFailedErrF error: "{err}"
-func NewJSSourceConsumerSetupFailedError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSSourceConsumerSetupFailedErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSSourceMaxMessageSizeTooBigError creates a new JSSourceMaxMessageSizeTooBigErr error: "stream source must have max message size >= target"
-func NewJSSourceMaxMessageSizeTooBigError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSSourceMaxMessageSizeTooBigErr]
-}
-
-// NewJSStorageResourcesExceededError creates a new JSStorageResourcesExceededErr error: "insufficient storage resources available"
-func NewJSStorageResourcesExceededError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStorageResourcesExceededErr]
-}
-
-// NewJSStreamAssignmentError creates a new JSStreamAssignmentErrF error: "{err}"
-func NewJSStreamAssignmentError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamAssignmentErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamCreateError creates a new JSStreamCreateErrF error: "{err}"
-func NewJSStreamCreateError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamCreateErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamDeleteError creates a new JSStreamDeleteErrF error: "{err}"
-func NewJSStreamDeleteError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamDeleteErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamExternalApiOverlapError creates a new JSStreamExternalApiOverlapErrF error: "stream external api prefix {prefix} must not overlap with {subject}"
-func NewJSStreamExternalApiOverlapError(prefix interface{}, subject interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamExternalApiOverlapErrF]
-	args := e.toReplacerArgs([]interface{}{"{prefix}", prefix, "{subject}", subject})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamExternalDelPrefixOverlapsError creates a new JSStreamExternalDelPrefixOverlapsErrF error: "stream external delivery prefix {prefix} overlaps with stream subject {subject}"
-func NewJSStreamExternalDelPrefixOverlapsError(prefix interface{}, subject interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamExternalDelPrefixOverlapsErrF]
-	args := e.toReplacerArgs([]interface{}{"{prefix}", prefix, "{subject}", subject})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamGeneralError creates a new JSStreamGeneralErrorF error: "{err}"
-func NewJSStreamGeneralError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamGeneralErrorF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamInvalidConfigError creates a new JSStreamInvalidConfigF error: "{err}"
-func NewJSStreamInvalidConfigError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamInvalidConfigF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamInvalidError creates a new JSStreamInvalidErr error: "stream not valid"
-func NewJSStreamInvalidError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamInvalidErr]
-}
-
-// NewJSStreamInvalidExternalDeliverySubjError creates a new JSStreamInvalidExternalDeliverySubjErrF error: "stream external delivery prefix {prefix} must not contain wildcards"
-func NewJSStreamInvalidExternalDeliverySubjError(prefix interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamInvalidExternalDeliverySubjErrF]
-	args := e.toReplacerArgs([]interface{}{"{prefix}", prefix})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamLimitsError creates a new JSStreamLimitsErrF error: "{err}"
-func NewJSStreamLimitsError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamLimitsErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamMessageExceedsMaximumError creates a new JSStreamMessageExceedsMaximumErr error: "message size exceeds maximum allowed"
-func NewJSStreamMessageExceedsMaximumError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamMessageExceedsMaximumErr]
-}
-
-// NewJSStreamMirrorNotUpdatableError creates a new JSStreamMirrorNotUpdatableErr error: "Mirror configuration can not be updated"
-func NewJSStreamMirrorNotUpdatableError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamMirrorNotUpdatableErr]
-}
-
-// NewJSStreamMismatchError creates a new JSStreamMismatchErr error: "stream name in subject does not match request"
-func NewJSStreamMismatchError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamMismatchErr]
-}
-
-// NewJSStreamMsgDeleteFailedError creates a new JSStreamMsgDeleteFailedF error: "{err}"
-func NewJSStreamMsgDeleteFailedError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamMsgDeleteFailedF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamNameExistError creates a new JSStreamNameExistErr error: "stream name already in use"
-func NewJSStreamNameExistError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamNameExistErr]
-}
-
-// NewJSStreamNotFoundError creates a new JSStreamNotFoundErr error: "stream not found"
-func NewJSStreamNotFoundError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamNotFoundErr]
-}
-
-// NewJSStreamNotMatchError creates a new JSStreamNotMatchErr error: "expected stream does not match"
-func NewJSStreamNotMatchError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamNotMatchErr]
-}
-
-// NewJSStreamReplicasNotSupportedError creates a new JSStreamReplicasNotSupportedErr error: "replicas > 1 not supported in non-clustered mode"
-func NewJSStreamReplicasNotSupportedError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamReplicasNotSupportedErr]
-}
-
-// NewJSStreamReplicasNotUpdatableError creates a new JSStreamReplicasNotUpdatableErr error: "Replicas configuration can not be updated"
-func NewJSStreamReplicasNotUpdatableError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamReplicasNotUpdatableErr]
-}
-
-// NewJSStreamRestoreError creates a new JSStreamRestoreErrF error: "restore failed: {err}"
-func NewJSStreamRestoreError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamRestoreErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamSequenceNotMatchError creates a new JSStreamSequenceNotMatchErr error: "expected stream sequence does not match"
-func NewJSStreamSequenceNotMatchError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamSequenceNotMatchErr]
-}
-
-// NewJSStreamSnapshotError creates a new JSStreamSnapshotErrF error: "snapshot failed: {err}"
-func NewJSStreamSnapshotError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamSnapshotErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamStoreFailedError creates a new JSStreamStoreFailedF error: "{err}"
-func NewJSStreamStoreFailedError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamStoreFailedF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamSubjectOverlapError creates a new JSStreamSubjectOverlapErr error: "subjects overlap with an existing stream"
-func NewJSStreamSubjectOverlapError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamSubjectOverlapErr]
-}
-
-// NewJSStreamTemplateCreateError creates a new JSStreamTemplateCreateErrF error: "{err}"
-func NewJSStreamTemplateCreateError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamTemplateCreateErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamTemplateDeleteError creates a new JSStreamTemplateDeleteErrF error: "{err}"
-func NewJSStreamTemplateDeleteError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamTemplateDeleteErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamTemplateNotFoundError creates a new JSStreamTemplateNotFoundErr error: "template not found"
-func NewJSStreamTemplateNotFoundError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSStreamTemplateNotFoundErr]
-}
-
-// NewJSStreamUpdateError creates a new JSStreamUpdateErrF error: "{err}"
-func NewJSStreamUpdateError(err error, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamUpdateErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamWrongLastMsgIDError creates a new JSStreamWrongLastMsgIDErrF error: "wrong last msg ID: {id}"
-func NewJSStreamWrongLastMsgIDError(id interface{}, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamWrongLastMsgIDErrF]
-	args := e.toReplacerArgs([]interface{}{"{id}", id})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSStreamWrongLastSequenceError creates a new JSStreamWrongLastSequenceErrF error: "wrong last sequence: {seq}"
-func NewJSStreamWrongLastSequenceError(seq uint64, opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	e := ApiErrors[JSStreamWrongLastSequenceErrF]
-	args := e.toReplacerArgs([]interface{}{"{seq}", seq})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
-}
-
-// NewJSTempStorageFailedError creates a new JSTempStorageFailedErr error: "JetStream unable to open temp storage for restore"
-func NewJSTempStorageFailedError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSTempStorageFailedErr]
-}
-
-// NewJSTemplateNameNotMatchSubjectError creates a new JSTemplateNameNotMatchSubjectErr error: "template name in subject does not match request"
-func NewJSTemplateNameNotMatchSubjectError(opts ...ErrorOption) *ApiError {
-	eopts := parseOpts(opts)
-	if ae, ok := eopts.err.(*ApiError); ok {
-		return ae
-	}
-
-	return ApiErrors[JSTemplateNameNotMatchSubjectErr]
-}
diff --git a/server/mqtt.go b/server/mqtt.go
index 5263158f..7c7937cf 100644
--- a/server/mqtt.go
+++ b/server/mqtt.go
@@ -1236,43 +1236,43 @@ func (as *mqttAccountSessionManager) processJSAPIReplies(_ *subscription, pc *cl
 	case mqttJSAStreamCreate:
 		var resp = &JSApiStreamCreateResponse{}
 		if err := json.Unmarshal(msg, resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAStreamLookup:
 		var resp = &JSApiStreamInfoResponse{}
 		if err := json.Unmarshal(msg, &resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAStreamDel:
 		var resp = &JSApiStreamDeleteResponse{}
 		if err := json.Unmarshal(msg, &resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAConsumerCreate:
 		var resp = &JSApiConsumerCreateResponse{}
 		if err := json.Unmarshal(msg, resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAConsumerDel:
 		var resp = &JSApiConsumerDeleteResponse{}
 		if err := json.Unmarshal(msg, resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAMsgStore, mqttJSASessPersist:
 		var resp = &JSPubAckResponse{}
 		if err := json.Unmarshal(msg, resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	case mqttJSAMsgLoad:
 		var resp = &JSApiMsgGetResponse{}
 		if err := json.Unmarshal(msg, resp); err != nil {
-			resp.Error = NewJSInvalidJSONError()
+			resp.Error = ApiErrors[JSInvalidJSONErr]
 		}
 		ch <- resp
 	default:
diff --git a/server/stream.go b/server/stream.go
index e8bae834..3a48745b 100644
--- a/server/stream.go
+++ b/server/stream.go
@@ -176,6 +176,9 @@ type stream struct {
 	// Indicates we have direct consumers.
 	directs int
 
+	// For flowcontrol processing for source and mirror internal consumers.
+	fcr map[uint64]string
+
 	// TODO(dlc) - Hide everything below behind two pointers.
 	// Clustered mode.
 	sa       *streamAssignment
@@ -198,6 +201,7 @@ type sourceInfo struct {
 	msgs  *inbound
 	sseq  uint64
 	dseq  uint64
+	clseq uint64
 	lag   uint64
 	err   *ApiError
 	last  time.Time
@@ -216,7 +220,6 @@ const (
 	JSStreamSource        = "Nats-Stream-Source"
 	JSLastConsumerSeq     = "Nats-Last-Consumer"
 	JSLastStreamSeq       = "Nats-Last-Stream"
-	JSConsumerStalled     = "Nats-Consumer-Stalled"
 )
 
 // Dedupe entry
@@ -257,7 +260,7 @@ func (a *Account) addStreamWithAssignment(config *StreamConfig, fsConfig *FileSt
 	// Sensible defaults.
 	cfg, err := checkStreamCfg(config)
 	if err != nil {
-		return nil, NewJSStreamInvalidConfigError(err, Unless(err))
+		return nil, ApiErrors[JSStreamInvalidConfigF].ErrOrNewT(err, "{err}", err)
 	}
 
 	singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode()
@@ -465,7 +468,7 @@ func (mset *stream) setStreamAssignment(sa *streamAssignment) {
 
 // Lock should be held.
 func (mset *stream) isLeader() bool {
-	if mset.isClustered() {
+	if mset.node != nil {
 		return mset.node.Leader()
 	}
 	return true
@@ -770,9 +773,6 @@ func checkStreamCfg(config *StreamConfig) (StreamConfig, error) {
 	if cfg.MaxMsgs == 0 {
 		cfg.MaxMsgs = -1
 	}
-	if cfg.MaxMsgsPer == 0 {
-		cfg.MaxMsgsPer = -1
-	}
 	if cfg.MaxBytes == 0 {
 		cfg.MaxBytes = -1
 	}
@@ -838,31 +838,31 @@ func (mset *stream) fileStoreConfig() (FileStoreConfig, error) {
 func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig) (*StreamConfig, error) {
 	cfg, err := checkStreamCfg(new)
 	if err != nil {
-		return nil, NewJSStreamInvalidConfigError(err, Unless(err))
+		return nil, ApiErrors[JSStreamInvalidConfigF].ErrOrNewT(err, "{err}", err)
 	}
 
 	// Name must match.
 	if cfg.Name != old.Name {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration name must match original"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration name must match original")
 	}
 	// Can't change MaxConsumers for now.
 	if cfg.MaxConsumers != old.MaxConsumers {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change MaxConsumers"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration update can not change MaxConsumers")
 	}
 	// Can't change storage types.
 	if cfg.Storage != old.Storage {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change storage type"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration update can not change storage type")
 	}
 	// Can't change retention.
 	if cfg.Retention != old.Retention {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change retention policy"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration update can not change retention policy")
 	}
 	// Can not have a template owner for now.
 	if old.Template != _EMPTY_ {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update not allowed on template owned stream"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration update not allowed on template owned stream")
 	}
 	if cfg.Template != _EMPTY_ {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not be owned by a template"))
+		return nil, ApiErrors[JSStreamInvalidConfigF].NewT("{err}", "stream configuration update can not be owned by a template")
 	}
 
 	// Check limits.
@@ -877,7 +877,7 @@ func (mset *stream) update(config *StreamConfig) error {
 	ocfg := mset.config()
 	cfg, err := mset.jsa.configUpdateCheck(&ocfg, config)
 	if err != nil {
-		return NewJSStreamInvalidConfigError(err, Unless(err))
+		return ApiErrors[JSStreamInvalidConfigF].ErrOrNewT(err, "{err}", err)
 	}
 
 	mset.mu.Lock()
@@ -1295,12 +1295,9 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool {
 		if m.rply != _EMPTY_ {
 			mset.handleFlowControl(mset.mirror, m)
 		} else {
-			// For idle heartbeats make sure we did not miss anything and check if we are considered stalled.
+			// For idle heartbeats make sure we did not miss anything.
 			if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != mset.mirror.dseq {
 				needsRetry = true
-			} else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 {
-				// Other side thinks we are stalled, so send flow control reply.
-				mset.outq.sendMsg(string(fcReply), nil)
 			}
 		}
 		mset.mu.Unlock()
@@ -1318,7 +1315,7 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool {
 	}
 
 	// Mirror info tracking.
-	olag, osseq, odseq := mset.mirror.lag, mset.mirror.sseq, mset.mirror.dseq
+	olag, osseq, odseq, oclseq := mset.mirror.lag, mset.mirror.sseq, mset.mirror.dseq, mset.mirror.clseq
 	if sseq == mset.mirror.sseq+1 {
 		mset.mirror.dseq = dseq
 		mset.mirror.sseq++
@@ -1348,6 +1345,7 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool {
 		mset.mirror.lag = pending - 1
 	}
 
+	mset.mirror.clseq = sseq - 1
 	js, stype := mset.js, mset.cfg.Storage
 	mset.mu.Unlock()
 
@@ -1371,6 +1369,7 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool {
 				mset.mirror.lag = olag
 				mset.mirror.sseq = osseq
 				mset.mirror.dseq = odseq
+				mset.mirror.clseq = oclseq
 				mset.mu.Unlock()
 				return false
 			} else {
@@ -1593,7 +1592,7 @@ func (mset *stream) setupMirrorConsumer() error {
 					mset.queueInbound(msgs, subject, reply, hdr, msg)
 				})
 				if err != nil {
-					mset.mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err))
+					mset.mirror.err = ApiErrors[JSMirrorConsumerSetupFailedErrF].ErrOrNewT(err, "{err}", err)
 					mset.mirror.sub = nil
 					mset.mirror.cname = _EMPTY_
 				} else {
@@ -1782,7 +1781,7 @@ func (mset *stream) setSourceConsumer(iname string, seq uint64) {
 						mset.queueInbound(si.msgs, subject, reply, hdr, msg)
 					})
 					if err != nil {
-						si.err = NewJSSourceConsumerSetupFailedError(err, Unless(err))
+						si.err = ApiErrors[JSSourceConsumerSetupFailedErrF].ErrOrNewT(err, "{err}", err)
 						si.sub = nil
 					} else {
 						si.err = nil
@@ -1866,21 +1865,15 @@ func (m *inMsg) isControlMsg() bool {
 	return len(m.msg) == 0 && len(m.hdr) > 0 && bytes.HasPrefix(m.hdr, []byte("NATS/1.0 100 "))
 }
 
-// Sends a reply to a flow control request.
-func (mset *stream) sendFlowControlReply(reply string) {
-	mset.mu.Lock()
-	if mset.isLeader() && mset.outq != nil {
-		mset.outq.sendMsg(reply, nil)
-	}
-	mset.mu.Unlock()
-}
-
-// handleFlowControl will properly handle flow control messages for both R==1 and R>1.
+// handleFlowControl will properly handle flow control messages for both R1 and R>1.
 // Lock should be held.
 func (mset *stream) handleFlowControl(si *sourceInfo, m *inMsg) {
-	// If we are clustered we will send the flow control message through the replication stack.
-	if mset.isClustered() {
-		mset.node.Propose(encodeStreamMsg(_EMPTY_, m.rply, m.hdr, nil, 0, 0))
+	// If we are clustered we want to delay signaling back the the upstream consumer.
+	if node := mset.node; node != nil && si.clseq > 0 {
+		if mset.fcr == nil {
+			mset.fcr = make(map[uint64]string)
+		}
+		mset.fcr[si.clseq] = m.rply
 	} else {
 		mset.outq.sendMsg(m.rply, nil)
 	}
@@ -1919,9 +1912,6 @@ func (mset *stream) processInboundSourceMsg(si *sourceInfo, m *inMsg) bool {
 			if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != si.dseq {
 				needsRetry = true
 				mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1)
-			} else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 {
-				// Other side thinks we are stalled, so send flow control reply.
-				mset.outq.sendMsg(string(fcReply), nil)
 			}
 		}
 		mset.mu.Unlock()
@@ -1970,9 +1960,15 @@ func (mset *stream) processInboundSourceMsg(si *sourceInfo, m *inMsg) bool {
 	hdr = genHeader(hdr, JSStreamSource, si.genSourceHeader(m.rply))
 
 	var err error
+	var clseq uint64
 	// If we are clustered we need to propose this message to the underlying raft group.
 	if node != nil {
-		err = mset.processClusteredInboundMsg(m.subj, _EMPTY_, hdr, msg)
+		clseq, err = mset.processClusteredInboundMsg(m.subj, _EMPTY_, hdr, msg)
+		if err == nil {
+			mset.mu.Lock()
+			si.clseq = clseq
+			mset.mu.Unlock()
+		}
 	} else {
 		err = mset.processJetStreamMsg(m.subj, _EMPTY_, hdr, msg, 0, 0)
 	}
@@ -2644,7 +2640,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 			mset.mu.Unlock()
 			if canRespond {
 				resp.PubAck = &PubAck{Stream: name}
-				resp.Error = NewJSStreamNotMatchError()
+				resp.Error = ApiErrors[JSStreamNotMatchErr]
 				b, _ := json.Marshal(resp)
 				outq.sendMsg(reply, b)
 			}
@@ -2657,7 +2653,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 			mset.mu.Unlock()
 			if canRespond {
 				resp.PubAck = &PubAck{Stream: name}
-				resp.Error = NewJSStreamWrongLastSequenceError(mlseq)
+				resp.Error = ApiErrors[JSStreamWrongLastSequenceErrF].NewT("{seq}", mlseq)
 				b, _ := json.Marshal(resp)
 				outq.sendMsg(reply, b)
 			}
@@ -2670,7 +2666,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 			mset.mu.Unlock()
 			if canRespond {
 				resp.PubAck = &PubAck{Stream: name}
-				resp.Error = NewJSStreamWrongLastMsgIDError(last)
+				resp.Error = ApiErrors[JSStreamWrongLastMsgIDErrF].NewT("{id}", last)
 				b, _ := json.Marshal(resp)
 				outq.sendMsg(reply, b)
 			}
@@ -2685,7 +2681,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 				mset.mu.Unlock()
 				if canRespond {
 					resp.PubAck = &PubAck{Stream: name}
-					resp.Error = NewJSStreamWrongLastSequenceError(lseq)
+					resp.Error = ApiErrors[JSStreamWrongLastSequenceErrF].NewT("{seq}", lseq)
 					b, _ := json.Marshal(resp)
 					outq.sendMsg(reply, b)
 				}
@@ -2707,7 +2703,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 		mset.mu.Unlock()
 		if canRespond {
 			resp.PubAck = &PubAck{Stream: name}
-			resp.Error = NewJSStreamMessageExceedsMaximumError()
+			resp.Error = ApiErrors[JSStreamMessageExceedsMaximumErr]
 			b, _ := json.Marshal(resp)
 			mset.outq.sendMsg(reply, b)
 		}
@@ -2721,7 +2717,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 		mset.mu.Unlock()
 		if canRespond {
 			resp.PubAck = &PubAck{Stream: name}
-			resp.Error = NewJSInsufficientResourcesError()
+			resp.Error = ApiErrors[JSInsufficientResourcesErr]
 			b, _ := json.Marshal(resp)
 			mset.outq.sendMsg(reply, b)
 		}
@@ -2729,7 +2725,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 		if node := mset.raftNode(); node != nil {
 			node.StepDown()
 		}
-		return NewJSInsufficientResourcesError()
+		return ApiErrors[JSInsufficientResourcesErr]
 	}
 
 	var noInterest bool
@@ -2814,14 +2810,14 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 
 		if canRespond {
 			resp.PubAck = &PubAck{Stream: name}
-			resp.Error = NewJSStreamStoreFailedError(err, Unless(err))
+			resp.Error = ApiErrors[JSStreamStoreFailedF].ErrOrNewT(err, "{err}", err)
 			response, _ = json.Marshal(resp)
 		}
 	} else if jsa.limitsExceeded(stype) {
 		s.Warnf("JetStream resource limits exceeded for account: %q", accName)
 		if canRespond {
 			resp.PubAck = &PubAck{Stream: name}
-			resp.Error = NewJSAccountResourcesExceededError()
+			resp.Error = ApiErrors[JSAccountResourcesExceededErr]
 			response, _ = json.Marshal(resp)
 		}
 		// If we did not succeed put those values back.
@@ -3055,7 +3051,7 @@ func (mset *stream) stop(deleteFlag, advisory bool) error {
 	mset.mu.RUnlock()
 
 	if jsa == nil {
-		return NewJSNotEnabledForAccountError()
+		return ApiErrors[JSNotEnabledForAccountErr]
 	}
 
 	// Remove from our account map.
@@ -3346,7 +3342,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 
 	cfg, err := checkStreamCfg(ncfg)
 	if err != nil {
-		return nil, NewJSStreamNotFoundError(Unless(err))
+		return nil, ApiErrors[JSStreamNotFoundErr].ErrOr(err)
 	}
 
 	_, jsa, err := a.checkForJetStream()
@@ -3406,7 +3402,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 
 	// See if this stream already exists.
 	if _, err := a.lookupStream(cfg.Name); err == nil {
-		return nil, NewJSStreamNameExistError()
+		return nil, ApiErrors[JSStreamNameExistErr]
 	}
 	// Move into the correct place here.
 	ndir := path.Join(jsa.storeDir, streamsDir, cfg.Name)
diff --git a/vendor/github.com/nats-io/nats.go/context.go b/vendor/github.com/nats-io/nats.go/context.go
index 53e5ebb0..b098a6d7 100644
--- a/vendor/github.com/nats-io/nats.go/context.go
+++ b/vendor/github.com/nats-io/nats.go/context.go
@@ -110,7 +110,10 @@ func (nc *Conn) oldRequestWithContext(ctx context.Context, subj string, hdr, dat
 	return s.NextMsgWithContext(ctx)
 }
 
-func (s *Subscription) nextMsgWithContext(ctx context.Context, pullSubInternal, waitIfNoMsg bool) (*Msg, error) {
+// NextMsgWithContext takes a context and returns the next message
+// available to a synchronous subscriber, blocking until it is delivered
+// or context gets canceled.
+func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) {
 	if ctx == nil {
 		return nil, ErrInvalidContext
 	}
@@ -123,11 +126,6 @@ func (s *Subscription) nextMsgWithContext(ctx context.Context, pullSubInternal,
 
 	s.mu.Lock()
 	err := s.validateNextMsgState()
-	// Unless this is from an internal call, reject use of this API.
-	// Users should use Fetch() instead.
-	if err == nil && !pullSubInternal && s.jsi != nil && s.jsi.pull {
-		err = ErrTypeSubscription
-	}
 	if err != nil {
 		s.mu.Unlock()
 		return nil, err
@@ -152,11 +150,6 @@ func (s *Subscription) nextMsgWithContext(ctx context.Context, pullSubInternal,
 			return msg, nil
 		}
 	default:
-		// If internal and we don't want to wait, signal that there is no
-		// message in the internal queue.
-		if pullSubInternal && !waitIfNoMsg {
-			return nil, errNoMessages
-		}
 	}
 
 	select {
@@ -174,13 +167,6 @@ func (s *Subscription) nextMsgWithContext(ctx context.Context, pullSubInternal,
 	return msg, nil
 }
 
-// NextMsgWithContext takes a context and returns the next message
-// available to a synchronous subscriber, blocking until it is delivered
-// or context gets canceled.
-func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) {
-	return s.nextMsgWithContext(ctx, false, true)
-}
-
 // FlushWithContext will allow a context to control the duration
 // of a Flush() call. This context should be non-nil and should
 // have a deadline set. We will return an error if none is present.
diff --git a/vendor/github.com/nats-io/nats.go/js.go b/vendor/github.com/nats-io/nats.go/js.go
index 6f843bef..0e68192a 100644
--- a/vendor/github.com/nats-io/nats.go/js.go
+++ b/vendor/github.com/nats-io/nats.go/js.go
@@ -88,12 +88,6 @@ const (
 
 	// apiMsgDeleteT is the endpoint to remove a message.
 	apiMsgDeleteT = "STREAM.MSG.DELETE.%s"
-
-	// orderedHeartbeatsInterval is how fast we want HBs from the server during idle.
-	orderedHeartbeatsInterval = 5 * time.Second
-
-	// Scale for threshold of missed HBs or lack of activity.
-	hbcThresh = 2
 )
 
 // JetStream allows persistent messaging through JetStream.
@@ -400,6 +394,27 @@ func (paf *pubAckFuture) Msg() *Msg {
 	return paf.msg
 }
 
+// pullSubscribe creates the wildcard subscription used per pull subscriber
+// to make fetch requests.
+func (js *js) pullSubscribe(subj string) (*Subscription, error) {
+	jsi := &jsSub{js: js, pull: true}
+
+	// Similar to async request handler we create a wildcard subscription for making requests,
+	// though we do not use the token based approach since we cannot match the response to
+	// the requestor due to JS subject being remapped on delivery.  Instead, we just use an array
+	// of channels similar to how ping/pong interval is handled and send the message to the first
+	// available requestor via a channel.
+	jsi.rr = rand.New(rand.NewSource(time.Now().UnixNano()))
+	jsi.rpre = fmt.Sprintf("%s.", NewInbox())
+	sub, err := js.nc.Subscribe(fmt.Sprintf("%s*", jsi.rpre), jsi.handleFetch)
+	if err != nil {
+		return nil, err
+	}
+	jsi.psub = sub
+
+	return &Subscription{Subject: subj, conn: js.nc, typ: PullSubscription, jsi: jsi}, nil
+}
+
 // For quick token lookup etc.
 const aReplyPreLen = 14
 const aReplyTokensize = 6
@@ -812,11 +827,14 @@ type nextRequest struct {
 
 // jsSub includes JetStream subscription info.
 type jsSub struct {
-	mu sync.RWMutex
 	js *js
 
-	// For pull subscribers, this is the next message subject to send requests to.
-	nms string
+	// To setup request mux handler for pull subscribers.
+	mu    sync.RWMutex
+	psub  *Subscription
+	rpre  string
+	rr    *rand.Rand
+	freqs []chan *Msg
 
 	consumer string
 	stream   string
@@ -825,40 +843,100 @@ type jsSub struct {
 	durable  bool
 	attached bool
 
-	// Ordered consumers
-	ordered bool
-	dseq    uint64
-	sseq    uint64
-	ccreq   *createConsumerRequest
-
 	// Heartbeats and Flow Control handling from push consumers.
-	hbc    *time.Timer
-	hbi    time.Duration
-	hbs    bool
-	active bool
-	fc     bool
-	cmeta  string
-	fcs    map[uint64]string
+	hbs   bool
+	fc    bool
+	cmeta string
+	fcs   map[uint64]string
 }
 
-func (jsi *jsSub) unsubscribe(drainMode bool) error {
+// newFetchReply generates a unique inbox used for a fetch request.
+func (jsi *jsSub) newFetchReply() string {
 	jsi.mu.Lock()
-	durable, attached := jsi.durable, jsi.attached
-	stream, consumer := jsi.stream, jsi.consumer
-	js := jsi.js
-	if jsi.hbc != nil {
-		jsi.hbc.Stop()
-		jsi.hbc = nil
+	rpre := jsi.rpre
+	rn := jsi.rr.Int63()
+	jsi.mu.Unlock()
+	var sb strings.Builder
+	sb.WriteString(rpre)
+	var b [aReplyTokensize]byte
+	for i, l := 0, rn; i < len(b); i++ {
+		b[i] = rdigits[l%base]
+		l /= base
+	}
+	sb.Write(b[:])
+	return sb.String()
+}
+
+// handleFetch is delivered a message requested by pull subscribers
+// when calling Fetch.
+func (jsi *jsSub) handleFetch(m *Msg) {
+	jsi.mu.Lock()
+	if len(jsi.freqs) == 0 {
+		nc := jsi.js.nc
+		sub := jsi.psub
+		nc.mu.Lock()
+		errCB := nc.Opts.AsyncErrorCB
+		err := fmt.Errorf("nats: fetch response delivered but requestor has gone away")
+		if errCB != nil {
+			nc.ach.push(func() { errCB(nc, sub, err) })
+		}
+		nc.mu.Unlock()
+		jsi.mu.Unlock()
+		return
+	}
+	mch := jsi.freqs[0]
+	if len(jsi.freqs) > 1 {
+		jsi.freqs = append(jsi.freqs[:0], jsi.freqs[1:]...)
+	} else {
+		jsi.freqs = jsi.freqs[:0]
 	}
 	jsi.mu.Unlock()
+	mch <- m
+}
+
+// fetchNoWait makes a request to get a single message using no wait.
+func (jsi *jsSub) fetchNoWait(ctx context.Context, subj string, payload []byte) (*Msg, error) {
+	nc := jsi.js.nc
+	m := NewMsg(subj)
+	m.Reply = jsi.newFetchReply()
+	m.Data = payload
+
+	mch := make(chan *Msg, 1)
+	jsi.mu.Lock()
+	jsi.freqs = append(jsi.freqs, mch)
+	jsi.mu.Unlock()
+	if err := nc.PublishMsg(m); err != nil {
+		return nil, err
+	}
 
-	if drainMode && (durable || attached) {
+	var ok bool
+	var msg *Msg
+
+	select {
+	case msg, ok = <-mch:
+		if !ok {
+			return nil, ErrConnectionClosed
+		}
+	case <-ctx.Done():
+		return nil, ctx.Err()
+	}
+
+	return msg, nil
+}
+
+func (jsi *jsSub) unsubscribe(drainMode bool) error {
+	if drainMode && (jsi.durable || jsi.attached) {
 		// Skip deleting consumer for durables/attached
 		// consumers when using drain mode.
 		return nil
 	}
+	// Clear the extra async pull subscription used for fetch requests.
+	if jsi.psub != nil {
+		jsi.psub.Drain()
+	}
 
-	return js.DeleteConsumer(stream, consumer)
+	js := jsi.js
+	return js.DeleteConsumer(jsi.stream, jsi.consumer)
 }
 
 // SubOpt configures options for subscribing to JetStream consumers.
@@ -878,13 +956,13 @@ func (js *js) Subscribe(subj string, cb MsgHandler, opts ...SubOpt) (*Subscripti
 	if cb == nil {
 		return nil, ErrBadSubscription
 	}
-	return js.subscribe(subj, _EMPTY_, cb, nil, false, false, opts)
+	return js.subscribe(subj, _EMPTY_, cb, nil, false, opts)
 }
 
 // SubscribeSync will create a sync subscription to the appropriate stream and consumer.
 func (js *js) SubscribeSync(subj string, opts ...SubOpt) (*Subscription, error) {
 	mch := make(chan *Msg, js.nc.Opts.SubChanLen)
-	return js.subscribe(subj, _EMPTY_, nil, mch, true, false, opts)
+	return js.subscribe(subj, _EMPTY_, nil, mch, true, opts)
 }
 
 // QueueSubscribe will create a subscription to the appropriate stream and consumer with queue semantics.
@@ -892,32 +970,31 @@ func (js *js) QueueSubscribe(subj, queue string, cb MsgHandler, opts ...SubOpt)
 	if cb == nil {
 		return nil, ErrBadSubscription
 	}
-	return js.subscribe(subj, queue, cb, nil, false, false, opts)
+	return js.subscribe(subj, queue, cb, nil, false, opts)
 }
 
 // QueueSubscribeSync will create a sync subscription to the appropriate stream and consumer with queue semantics.
 func (js *js) QueueSubscribeSync(subj, queue string, opts ...SubOpt) (*Subscription, error) {
 	mch := make(chan *Msg, js.nc.Opts.SubChanLen)
-	return js.subscribe(subj, queue, nil, mch, true, false, opts)
+	return js.subscribe(subj, queue, nil, mch, true, opts)
 }
 
 // ChanSubscribe will create a subscription to the appropriate stream and consumer using a channel.
 func (js *js) ChanSubscribe(subj string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) {
-	return js.subscribe(subj, _EMPTY_, nil, ch, false, false, opts)
+	return js.subscribe(subj, _EMPTY_, nil, ch, false, opts)
 }
 
 // ChanQueueSubscribe will create a subscription to the appropriate stream and consumer using a channel.
 func (js *js) ChanQueueSubscribe(subj, queue string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) {
-	return js.subscribe(subj, queue, nil, ch, false, false, opts)
+	return js.subscribe(subj, queue, nil, ch, false, opts)
 }
 
 // PullSubscribe creates a pull subscriber.
 func (js *js) PullSubscribe(subj, durable string, opts ...SubOpt) (*Subscription, error) {
-	mch := make(chan *Msg, js.nc.Opts.SubChanLen)
-	return js.subscribe(subj, _EMPTY_, nil, mch, true, true, append(opts, Durable(durable)))
+	return js.subscribe(subj, _EMPTY_, nil, nil, false, append(opts, Durable(durable)))
 }
 
-func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync, isPullMode bool, opts []SubOpt) (*Subscription, error) {
+func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync bool, opts []SubOpt) (*Subscription, error) {
 	cfg := ConsumerConfig{AckPolicy: ackPolicyNotSet}
 	o := subOpts{cfg: &cfg}
 	if len(opts) > 0 {
@@ -928,6 +1005,7 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		}
 	}
 
+	isPullMode := ch == nil && cb == nil && !isSync
 	badPullAck := o.cfg.AckPolicy == AckNonePolicy || o.cfg.AckPolicy == AckAllPolicy
 	hasHeartbeats := o.cfg.Heartbeat > 0
 	hasFC := o.cfg.FlowControl
@@ -948,49 +1026,8 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		consumerBound = o.bound
 		notFoundErr   bool
 		lookupErr     bool
-		nc            = js.nc
-		nms           string
 	)
 
-	// Do some quick checks here for ordered consumers. We do these here instead of spread out
-	// in the individual SubOpts.
-	if o.ordered {
-		// Make sure we are not durable.
-		if isDurable {
-			return nil, fmt.Errorf("nats: durable can not be set for an ordered consumer")
-		}
-		// Check ack policy.
-		if o.cfg.AckPolicy != ackPolicyNotSet {
-			return nil, fmt.Errorf("nats: ack policy can not be set for an ordered consumer")
-		}
-		// Check max deliver.
-		if o.cfg.MaxDeliver != 1 && o.cfg.MaxDeliver != 0 {
-			return nil, fmt.Errorf("nats: max deliver can not be set for an ordered consumer")
-		}
-		// Queue groups not allowed.
-		if queue != _EMPTY_ {
-			return nil, fmt.Errorf("nats: queues not be set for an ordered consumer")
-		}
-		// Check for bound consumers.
-		if consumer != _EMPTY_ {
-			return nil, fmt.Errorf("nats: can not bind existing consumer for an ordered consumer")
-		}
-		// Check for pull mode.
-		if isPullMode {
-			return nil, fmt.Errorf("nats: can not use pull mode for an ordered consumer")
-		}
-		// Setup how we need it to be here.
-		o.cfg.FlowControl = true
-		o.cfg.AckPolicy = AckNonePolicy
-		o.cfg.MaxDeliver = 1
-		o.cfg.AckWait = 22 * time.Hour // Just set to something known, not utilized.
-		if !hasHeartbeats {
-			o.cfg.Heartbeat = orderedHeartbeatsInterval
-		}
-		hasFC, hasHeartbeats = true, true
-		o.mack = true // To avoid auto-ack wrapping call below.
-	}
-
 	// In case a consumer has not been set explicitly, then the
 	// durable name will be used as the consumer name.
 	if consumer == _EMPTY_ {
@@ -1007,7 +1044,7 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		stream = o.stream
 	}
 
-	// With an explicit durable name, we can lookup the consumer first
+	// With an explicit durable name, then can lookup the consumer first
 	// to which it should be attaching to.
 	if consumer != _EMPTY_ {
 		info, err = js.ConsumerInfo(stream, consumer)
@@ -1032,24 +1069,26 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		} else if !isPullMode && ccfg.DeliverSubject == _EMPTY_ {
 			return nil, ErrPullSubscribeRequired
 		}
+
 		if ccfg.DeliverSubject != _EMPTY_ {
 			deliver = ccfg.DeliverSubject
 		} else if !isPullMode {
-			deliver = nc.newInbox()
+			deliver = NewInbox()
 		}
 	case (err != nil && !notFoundErr) || (notFoundErr && consumerBound):
-		// If the consumer is being bound and we got an error on pull subscribe then allow the error.
+		// If the consumer is being bound got an error on pull subscribe then allow the error.
 		if !(isPullMode && lookupErr && consumerBound) {
 			return nil, err
 		}
 	default:
 		// Attempt to create consumer if not found nor using Bind.
 		shouldCreate = true
-		if o.cfg.DeliverSubject != _EMPTY_ {
-			deliver = o.cfg.DeliverSubject
-		} else if !isPullMode {
-			deliver = nc.newInbox()
+		deliver = NewInbox()
+		if !isPullMode {
+			cfg.DeliverSubject = deliver
 		}
+		// Do filtering always, server will clear as needed.
+		cfg.FilterSubject = subj
 	}
 
 	var sub *Subscription
@@ -1060,17 +1099,23 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		cb = func(m *Msg) { ocb(m); m.Ack() }
 	}
 
-	// In case we need to hold onto it for ordered consumers.
-	var ccreq *createConsumerRequest
+	if isPullMode {
+		sub, err = js.pullSubscribe(subj)
+	} else {
+		sub, err = js.nc.subscribe(deliver, queue, cb, ch, isSync, &jsSub{js: js, hbs: hasHeartbeats, fc: hasFC})
+	}
+	if err != nil {
+		return nil, err
+	}
 
-	// If we are creating or updating let's update cfg.
-	if shouldCreate {
-		if !isPullMode {
-			cfg.DeliverSubject = deliver
-		}
-		// Do filtering always, server will clear as needed.
-		cfg.FilterSubject = subj
+	// With flow control enabled async subscriptions we will disable msgs
+	// limits, and set a larger pending bytes limit by default.
+	if !isPullMode && cb != nil && hasFC {
+		sub.SetPendingLimits(DefaultSubPendingMsgsLimit*16, DefaultSubPendingBytesLimit)
+	}
 
+	// If we are creating or updating let's process that request.
+	if shouldCreate {
 		// If not set default to ack explicit.
 		if cfg.AckPolicy == ackPolicyNotSet {
 			cfg.AckPolicy = AckExplicitPolicy
@@ -1079,74 +1124,17 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		// and set to the internal max.
 		// TODO(dlc) - We should be able to update this if client updates PendingLimits.
 		if cfg.MaxAckPending == 0 && cfg.AckPolicy != AckNonePolicy {
-			if !isPullMode && cb != nil && hasFC {
-				cfg.MaxAckPending = DefaultSubPendingMsgsLimit * 16
-			} else if ch != nil {
-				cfg.MaxAckPending = cap(ch)
-			} else {
-				cfg.MaxAckPending = DefaultSubPendingMsgsLimit
-			}
+			maxMsgs, _, _ := sub.PendingLimits()
+			cfg.MaxAckPending = maxMsgs
 		}
-		// Create request here.
-		ccreq = &createConsumerRequest{
+
+		req := &createConsumerRequest{
 			Stream: stream,
 			Config: &cfg,
 		}
-	}
-
-	if isPullMode {
-		nms = fmt.Sprintf(js.apiSubj(apiRequestNextT), stream, consumer)
-		deliver = nc.newInbox()
-	}
-
-	jsi := &jsSub{
-		js:       js,
-		stream:   stream,
-		consumer: consumer,
-		durable:  isDurable,
-		attached: attached,
-		deliver:  deliver,
-		hbs:      hasHeartbeats,
-		hbi:      o.cfg.Heartbeat,
-		fc:       hasFC,
-		ordered:  o.ordered,
-		ccreq:    ccreq,
-		dseq:     1,
-		pull:     isPullMode,
-		nms:      nms,
-	}
-
-	sub, err = nc.subscribe(deliver, queue, cb, ch, isSync, jsi)
-	// Since JetStream sends on different subject, make sure this reflects the user's intentions.
-	sub.mu.Lock()
-	sub.Subject = subj
-	sub.mu.Unlock()
-	if err != nil {
-		return nil, err
-	}
-
-	// With flow control enabled async subscriptions we will disable msgs
-	// limits, and set a larger pending bytes limit by default.
-	if !isPullMode && cb != nil && hasFC {
-		sub.SetPendingLimits(DefaultSubPendingMsgsLimit*16, DefaultSubPendingBytesLimit)
-	}
-
-	// If we fail and we had the sub we need to cleanup, but can't just do a straight Unsubscribe or Drain.
-	// We need to clear the jsi so we do not remove any durables etc.
-	cleanUpSub := func() {
-		if sub != nil {
-			sub.mu.Lock()
-			sub.jsi = nil
-			sub.mu.Unlock()
-			sub.Unsubscribe()
-		}
-	}
 
-	// If we are creating or updating let's process that request.
-	if shouldCreate {
-		j, err := json.Marshal(ccreq)
+		j, err := json.Marshal(req)
 		if err != nil {
-			cleanUpSub()
 			return nil, err
 		}
 
@@ -1157,9 +1145,9 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 			ccSubj = fmt.Sprintf(apiConsumerCreateT, stream)
 		}
 
-		resp, err := nc.Request(js.apiSubj(ccSubj), j, js.opts.wait)
+		resp, err := js.nc.Request(js.apiSubj(ccSubj), j, js.opts.wait)
 		if err != nil {
-			cleanUpSub()
+			sub.Drain()
 			if err == ErrNoResponders {
 				err = ErrJetStreamNotEnabled
 			}
@@ -1168,23 +1156,19 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 		var cinfo consumerResponse
 		err = json.Unmarshal(resp.Data, &cinfo)
 		if err != nil {
-			cleanUpSub()
+			sub.Drain()
 			return nil, err
 		}
 		info = cinfo.ConsumerInfo
-
 		if cinfo.Error != nil {
-			// We will not be using this sub here if we were push based.
-			if !isPullMode {
-				cleanUpSub()
-			}
+			// Remove interest from previous subscribe since it
+			// may have an incorrect delivery subject.
+			sub.Drain()
+
 			// Multiple subscribers could compete in creating the first consumer
 			// that will be shared using the same durable name. If this happens, then
 			// do a lookup of the consumer info and resubscribe using the latest info.
-			if consumer != _EMPTY_ &&
-				(strings.Contains(cinfo.Error.Description, `consumer already exists`) ||
-					strings.Contains(cinfo.Error.Description, `consumer name already in use`)) {
-
+			if consumer != _EMPTY_ && (strings.Contains(cinfo.Error.Description, `consumer already exists`) || strings.Contains(cinfo.Error.Description, `consumer name already in use`)) {
 				info, err = js.ConsumerInfo(stream, consumer)
 				if err != nil {
 					return nil, err
@@ -1196,44 +1180,37 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
 					return nil, ErrSubjectMismatch
 				}
 
-				// Update attached status.
-				jsi.attached = true
-
 				// Use the deliver subject from latest consumer config to attach.
-				if info.Config.DeliverSubject != _EMPTY_ {
+				if ccfg.DeliverSubject != _EMPTY_ {
 					// We can't reuse the channel, so if one was passed, we need to create a new one.
 					if ch != nil {
 						ch = make(chan *Msg, cap(ch))
 					}
-					jsi.deliver = info.Config.DeliverSubject
-					// Recreate the subscription here.
-					sub, err = nc.subscribe(jsi.deliver, queue, cb, ch, isSync, jsi)
+					sub, err = js.nc.subscribe(ccfg.DeliverSubject, queue, cb, ch, isSync,
+						&jsSub{js: js, hbs: hasHeartbeats, fc: hasFC})
 					if err != nil {
 						return nil, err
 					}
-					// Since JetStream sends on different subject, make sure this reflects the user's intentions.
-					sub.mu.Lock()
-					sub.Subject = subj
-					sub.mu.Unlock()
 				}
+				attached = true
 			} else {
 				if cinfo.Error.Code == 404 {
 					return nil, ErrStreamNotFound
 				}
 				return nil, fmt.Errorf("nats: %s", cinfo.Error.Description)
 			}
-		} else if consumer == _EMPTY_ {
-			// Update our consumer name here which is filled in when we create the consumer.
-			sub.mu.Lock()
-			sub.jsi.consumer = info.Name
-			sub.mu.Unlock()
 		}
+		stream = info.Stream
+		consumer = info.Name
+		deliver = info.Config.DeliverSubject
 	}
-
-	// Do heartbeats last if needed.
-	if hasHeartbeats {
-		sub.scheduleHeartbeatCheck()
-	}
+	sub.mu.Lock()
+	sub.jsi.stream = stream
+	sub.jsi.consumer = consumer
+	sub.jsi.durable = isDurable
+	sub.jsi.attached = attached
+	sub.jsi.deliver = deliver
+	sub.mu.Unlock()
 
 	return sub, nil
 }
@@ -1273,142 +1250,6 @@ func (jsi *jsSub) trackSequences(reply string) {
 	jsi.mu.Unlock()
 }
 
-// Check to make sure messages are arriving in order.
-// Returns true if the sub had to be replaced. Will cause upper layers to return.
-// Lock should be held.
-func (sub *Subscription) checkOrderedMsgs(m *Msg) bool {
-	// Ignore msgs with no reply like HBs and flowcontrol, they are handled elsewhere.
-	if m.Reply == _EMPTY_ || sub.jsi == nil || isControlMessage(m) {
-		return false
-	}
-
-	// Normal message here.
-	tokens, err := getMetadataFields(m.Reply)
-	if err != nil {
-		return false
-	}
-	sseq, dseq := uint64(parseNum(tokens[5])), uint64(parseNum(tokens[6]))
-
-	jsi := sub.jsi
-	jsi.mu.Lock()
-	if dseq != jsi.dseq {
-		rseq := jsi.sseq + 1
-		jsi.mu.Unlock()
-		sub.resetOrderedConsumer(rseq)
-		return true
-	}
-	// Update our tracking here.
-	jsi.dseq, jsi.sseq = dseq+1, sseq
-	jsi.mu.Unlock()
-	return false
-}
-
-// Update and replace sid.
-// Lock should be held on entry but will be unlocked to prevent lock inversion.
-func (sub *Subscription) applyNewSID() (osid int64) {
-	nc := sub.conn
-	sub.mu.Unlock()
-
-	nc.subsMu.Lock()
-	osid = sub.sid
-	delete(nc.subs, osid)
-	// Place new one.
-	nc.ssid++
-	nsid := nc.ssid
-	nc.subs[nsid] = sub
-	nc.subsMu.Unlock()
-
-	sub.mu.Lock()
-	sub.sid = nsid
-	return osid
-}
-
-// We are here if we have detected a gap with an ordered consumer.
-// We will create a new consumer and rewire the low level subscription.
-// Lock should be held.
-func (sub *Subscription) resetOrderedConsumer(sseq uint64) {
-	nc := sub.conn
-	closed := sub.closed
-	if sub.jsi == nil || nc == nil || closed {
-		return
-	}
-
-	// Quick unsubscribe. Since we know this is a simple push subscriber we do in place.
-	osid := sub.applyNewSID()
-
-	// Grab new inbox.
-	newDeliver := nc.newInbox()
-	sub.Subject = newDeliver
-
-	// Snapshot jsi under sub lock here.
-	jsi := sub.jsi
-
-	// We are still in the low level readloop for the connection so we need
-	// to spin a go routine to try to create the new consumer.
-	go func() {
-		// Unsubscribe and subscribe with new inbox and sid.
-		// Remap a new low level sub into this sub since its client accessible.
-		// This is done here in this go routine to prevent lock inversion.
-		nc.mu.Lock()
-		nc.bw.appendString(fmt.Sprintf(unsubProto, osid, _EMPTY_))
-		nc.bw.appendString(fmt.Sprintf(subProto, newDeliver, _EMPTY_, sub.sid))
-		nc.kickFlusher()
-		nc.mu.Unlock()
-
-		pushErr := func(err error) {
-			nc.handleConsumerSequenceMismatch(sub, err)
-			nc.unsubscribe(sub, 0, true)
-		}
-
-		jsi.mu.Lock()
-		// Reset some items in jsi.
-		jsi.dseq = 1
-		jsi.cmeta = _EMPTY_
-		jsi.fcs = nil
-		jsi.deliver = newDeliver
-		// Reset consumer request for starting policy.
-		cfg := jsi.ccreq.Config
-		cfg.DeliverSubject = newDeliver
-		cfg.DeliverPolicy = DeliverByStartSequencePolicy
-		cfg.OptStartSeq = sseq
-
-		ccSubj := fmt.Sprintf(apiConsumerCreateT, jsi.stream)
-		j, err := json.Marshal(jsi.ccreq)
-		js := jsi.js
-		jsi.mu.Unlock()
-
-		if err != nil {
-			pushErr(err)
-			return
-		}
-
-		resp, err := nc.Request(js.apiSubj(ccSubj), j, js.opts.wait)
-		if err != nil {
-			if err == ErrNoResponders {
-				err = ErrJetStreamNotEnabled
-			}
-			pushErr(err)
-			return
-		}
-
-		var cinfo consumerResponse
-		err = json.Unmarshal(resp.Data, &cinfo)
-		if err != nil {
-			pushErr(err)
-			return
-		}
-
-		if cinfo.Error != nil {
-			pushErr(fmt.Errorf("nats: %s", cinfo.Error.Description))
-			return
-		}
-
-		jsi.mu.Lock()
-		jsi.consumer = cinfo.Name
-		jsi.mu.Unlock()
-	}()
-}
-
 // checkForFlowControlResponse will check to see if we should send a flow control response
 // based on the delivered index.
 // Lock should be held.
@@ -1441,55 +1282,6 @@ func (jsi *jsSub) scheduleFlowControlResponse(dfuture uint64, reply string) {
 	jsi.mu.Unlock()
 }
 
-// Checks for activity from our consumer.
-// If we do not think we are active send an async error.
-func (sub *Subscription) activityCheck() {
-	jsi := sub.jsi
-	if jsi == nil {
-		return
-	}
-
-	jsi.mu.Lock()
-	active := jsi.active
-	jsi.hbc.Reset(jsi.hbi)
-	jsi.active = false
-	jsi.mu.Unlock()
-
-	if !active {
-		sub.mu.Lock()
-		nc := sub.conn
-		closed := sub.closed
-		sub.mu.Unlock()
-
-		if !closed {
-			nc.mu.Lock()
-			errCB := nc.Opts.AsyncErrorCB
-			if errCB != nil {
-				nc.ach.push(func() { errCB(nc, sub, ErrConsumerNotActive) })
-			}
-			nc.mu.Unlock()
-		}
-	}
-}
-
-// scheduleHeartbeatCheck sets up the timer check to make sure we are active
-// or receiving idle heartbeats..
-func (sub *Subscription) scheduleHeartbeatCheck() {
-	jsi := sub.jsi
-	if jsi == nil {
-		return
-	}
-
-	jsi.mu.Lock()
-	defer jsi.mu.Unlock()
-
-	if jsi.hbc == nil {
-		jsi.hbc = time.AfterFunc(jsi.hbi*hbcThresh, sub.activityCheck)
-	} else {
-		jsi.hbc.Reset(jsi.hbi)
-	}
-}
-
 // handleConsumerSequenceMismatch will send an async error that can be used to restart a push based consumer.
 func (nc *Conn) handleConsumerSequenceMismatch(sub *Subscription, err error) {
 	nc.mu.Lock()
@@ -1500,13 +1292,12 @@ func (nc *Conn) handleConsumerSequenceMismatch(sub *Subscription, err error) {
 	nc.mu.Unlock()
 }
 
-// checkForSequenceMismatch will make sure we have not missed any messages since last seen.
-func (nc *Conn) checkForSequenceMismatch(msg *Msg, s *Subscription, jsi *jsSub) {
+// processControlFlow will automatically respond to control messages sent by the server.
+func (nc *Conn) processSequenceMismatch(msg *Msg, s *Subscription, jsi *jsSub) {
 	// Process heartbeat received, get latest control metadata if present.
-	jsi.mu.Lock()
-	ctrl, ordered := jsi.cmeta, jsi.ordered
-	jsi.active = true
-	jsi.mu.Unlock()
+	jsi.mu.RLock()
+	ctrl := jsi.cmeta
+	jsi.mu.RUnlock()
 
 	if ctrl == _EMPTY_ {
 		return
@@ -1531,18 +1322,12 @@ func (nc *Conn) checkForSequenceMismatch(msg *Msg, s *Subscription, jsi *jsSub)
 		// Dispatch async error including details such as
 		// from where the consumer could be restarted.
 		sseq := parseNum(tokens[5])
-		if ordered {
-			s.mu.Lock()
-			s.resetOrderedConsumer(jsi.sseq + 1)
-			s.mu.Unlock()
-		} else {
-			ecs := &ErrConsumerSequenceMismatch{
-				StreamResumeSequence: uint64(sseq),
-				ConsumerSequence:     uint64(parseNum(dseq)),
-				LastConsumerSequence: uint64(parseNum(ldseq)),
-			}
-			nc.handleConsumerSequenceMismatch(s, ecs)
+		ecs := &ErrConsumerSequenceMismatch{
+			StreamResumeSequence: uint64(sseq),
+			ConsumerSequence:     uint64(parseNum(dseq)),
+			LastConsumerSequence: uint64(parseNum(ldseq)),
 		}
+		nc.handleConsumerSequenceMismatch(s, ecs)
 	}
 }
 
@@ -1583,24 +1368,12 @@ func (js *js) lookupStreamBySubject(subj string) (string, error) {
 type subOpts struct {
 	// For attaching.
 	stream, consumer string
+	// For manual ack
+	mack bool
 	// For creating or updating.
 	cfg *ConsumerConfig
 	// For binding a subscription to a consumer without creating it.
 	bound bool
-	// For manual ack
-	mack bool
-	// For an ordered consumer.
-	ordered bool
-}
-
-// OrderedConsumer will create a fifo direct/ephemeral consumer for in order delivery of messages.
-// There are no redeliveries and no acks, and flow control and heartbeats will be added but
-// will be taken care of without additional client code.
-func OrderedConsumer() SubOpt {
-	return subOptFn(func(opts *subOpts) error {
-		opts.ordered = true
-		return nil
-	})
 }
 
 // ManualAck disables auto ack functionality for async subscriptions.
@@ -1824,45 +1597,6 @@ func PullMaxWaiting(n int) SubOpt {
 
 var errNoMessages = errors.New("nats: no messages")
 
-// Returns if the given message is a user message or not, and if
-// `checkSts` is true, returns appropriate error based on the
-// content of the status (404, etc..)
-func checkMsg(msg *Msg, checkSts bool) (usrMsg bool, err error) {
-	// Assume user message
-	usrMsg = true
-
-	// If payload or no header, consider this a user message
-	if len(msg.Data) > 0 || len(msg.Header) == 0 {
-		return
-	}
-	// Look for status header
-	val := msg.Header.Get(statusHdr)
-	// If not present, then this is considered a user message
-	if val == _EMPTY_ {
-		return
-	}
-	// At this point, this is not a user message since there is
-	// no payload and a "Status" header.
-	usrMsg = false
-
-	// If we don't care about status, we are done.
-	if !checkSts {
-		return
-	}
-	switch val {
-	case noResponders:
-		err = ErrNoResponders
-	case noMessagesSts:
-		// 404 indicates that there are no messages.
-		err = errNoMessages
-	case reqTimeoutSts:
-		err = ErrTimeout
-	default:
-		err = fmt.Errorf("nats: %s", msg.Header.Get(descrHdr))
-	}
-	return
-}
-
 // Fetch pulls a batch of messages from a stream for a pull consumer.
 func (sub *Subscription) Fetch(batch int, opts ...PullOpt) ([]*Msg, error) {
 	if sub == nil {
@@ -1881,18 +1615,14 @@ func (sub *Subscription) Fetch(batch int, opts ...PullOpt) ([]*Msg, error) {
 
 	sub.mu.Lock()
 	jsi := sub.jsi
-	// Reject if this is not a pull subscription. Note that sub.typ is SyncSubscription,
-	// so check for jsi.pull boolean instead.
-	if jsi == nil || !jsi.pull {
+	if jsi == nil || sub.typ != PullSubscription {
 		sub.mu.Unlock()
 		return nil, ErrTypeSubscription
 	}
 
-	nc := sub.conn
-	nms := sub.jsi.nms
-	rply := sub.jsi.deliver
+	nc, _ := sub.conn, sub.Subject
+	stream, consumer := sub.jsi.stream, sub.jsi.consumer
 	js := sub.jsi.js
-	pmc := len(sub.mch) > 0
 
 	ttl := o.ttl
 	if ttl == 0 {
@@ -1926,6 +1656,22 @@ func (sub *Subscription) Fetch(batch int, opts ...PullOpt) ([]*Msg, error) {
 		return nil, err
 	}
 
+	// Check for empty payload message and process synchronously
+	// any status messages.
+	checkMsg := func(msg *Msg) error {
+		if len(msg.Data) == 0 {
+			switch msg.Header.Get(statusHdr) {
+			case noResponders:
+				return ErrNoResponders
+			case noMessages:
+				return errNoMessages
+			case "400", "408", "409":
+				return fmt.Errorf("nats: %s", msg.Header.Get(descrHdr))
+			}
+		}
+		return nil
+	}
+
 	checkCtxErr := func(err error) error {
 		if o.ctx == nil && err == context.DeadlineExceeded {
 			return ErrTimeout
@@ -1934,86 +1680,195 @@ func (sub *Subscription) Fetch(batch int, opts ...PullOpt) ([]*Msg, error) {
 	}
 
 	var (
-		msgs  = make([]*Msg, 0, batch)
-		msg   *Msg
-		start = time.Now()
+		gotNoMessages bool
+		nr            = &nextRequest{Batch: batch, NoWait: true}
+		req, _        = json.Marshal(nr)
+		reqNext       = js.apiSubj(fmt.Sprintf(apiRequestNextT, stream, consumer))
+		expires       = ttl - 10*time.Millisecond
+		msgs          = make([]*Msg, 0)
 	)
-	for pmc && len(msgs) < batch {
-		// Check next msg with booleans that say that this is an internal call
-		// for a pull subscribe (so don't reject it) and don't wait if there
-		// are no messages.
-		msg, err = sub.nextMsgWithContext(ctx, true, false)
+
+	if batch == 1 {
+		// To optimize single message no wait fetch, we use a shared wildcard
+		// subscription per pull subscriber to wait for the response.
+		resp, err := jsi.fetchNoWait(ctx, reqNext, req)
+		if err != nil {
+			return nil, checkCtxErr(err)
+		}
+
+		// In case of a no messages instant error, then fallback
+		// into longer version of pull batch request.
+		err = checkMsg(resp)
 		if err != nil {
 			if err == errNoMessages {
-				err = nil
+				// Use old request style for the retry of the pull request
+				// in order to use auto UNSUB 1 to prevent the server
+				// from delivering a message when there is no more interest.
+				nr.NoWait = false
+				nr.Expires = expires
+				req, _ = json.Marshal(nr)
+				resp, err = nc.oldRequestWithContext(ctx, reqNext, nil, req)
+				if err != nil {
+					return nil, checkCtxErr(err)
+				}
+
+				// This next message, could also be an error
+				// (e.g. 408 due to request timeout).
+				err = checkMsg(resp)
+				if err != nil {
+					return nil, err
+				}
+				return []*Msg{resp}, nil
+			} else {
+				// Hard error
+				return nil, checkCtxErr(err)
 			}
-			break
-		}
-		// Check msg but just to determine if this is a user message
-		// or status message, however, we don't care about values of status
-		// messages at this point in the Fetch() call, so checkMsg can't
-		// return an error.
-		if usrMsg, _ := checkMsg(msg, false); usrMsg {
-			msgs = append(msgs, msg)
 		}
+		return []*Msg{resp}, nil
 	}
-	if err == nil && len(msgs) < batch {
-		// For batch real size of 1, it does not make sense to set no_wait in
-		// the request.
-		batchSize := batch - len(msgs)
-		noWait := batchSize > 1
-		nr := &nextRequest{Batch: batchSize, NoWait: noWait}
-		req, _ := json.Marshal(nr)
 
-		err = nc.PublishRequest(nms, rply, req)
-		for err == nil && len(msgs) < batch {
-			ttl -= time.Since(start)
-			if ttl < 0 {
-				ttl = 0
-			}
+	// Setup a request where we will wait for the first response
+	// in case of errors, then dispatch the rest of the replies
+	// to the channel.
+	inbox := NewInbox()
+
+	mch := make(chan *Msg, batch)
+	s, err := nc.subscribe(inbox, _EMPTY_, nil, mch, true, nil)
+	if err != nil {
+		return nil, err
+	}
 
-			// Ask for next message and waits if there are no messages
-			msg, err = sub.nextMsgWithContext(ctx, true, true)
+	// Remove interest in the subscription at the end so that the
+	// this inbox does not get delivered the results intended
+	// for another request.
+	defer s.Unsubscribe()
+
+	// Make a publish request to get results of the pull.
+	err = nc.publish(reqNext, inbox, nil, req)
+	if err != nil {
+		s.Unsubscribe()
+		return nil, err
+	}
+
+	// Try to get the first message or error with NoWait.
+	var (
+		firstMsg *Msg
+		ok       bool
+	)
+	select {
+	case firstMsg, ok = <-mch:
+		if !ok {
+			err = s.getNextMsgErr()
+		} else {
+			err = s.processNextMsgDelivered(firstMsg)
 			if err == nil {
-				var usrMsg bool
-
-				usrMsg, err = checkMsg(msg, true)
-				if err == nil && usrMsg {
-					msgs = append(msgs, msg)
-				} else if noWait && (err == errNoMessages) && len(msgs) == 0 {
-					// If we have a 404 for our "no_wait" request and have
-					// not collected any message, then resend request to
-					// wait this time.
-					noWait = false
-
-					ttl -= time.Since(start)
-					if ttl < 0 {
-						// At this point consider that we have timed-out
-						err = context.DeadlineExceeded
-						break
-					}
+				err = checkMsg(firstMsg)
+			}
+		}
+	case <-ctx.Done():
+		err = checkCtxErr(ctx.Err())
+	}
 
-					// Make our request expiration a bit shorter than the
-					// current timeout.
-					expires := ttl
-					if ttl >= 20*time.Millisecond {
-						expires = ttl - 10*time.Millisecond
-					}
+	// If the first error is 'no more messages', then switch into
+	// longer form version of the request that waits for messages.
+	if err == errNoMessages {
+		gotNoMessages = true
+	} else if err != nil {
+		// We should be getting the response from the server
+		// in case we got a poll error, so stop and cleanup.
+		s.Unsubscribe()
+		return nil, err
+	}
 
-					nr.Batch = batch - len(msgs)
-					nr.Expires = expires
-					nr.NoWait = false
-					req, _ = json.Marshal(nr)
+	if gotNoMessages {
+		// We started with a 404 response right away, so fallback into
+		// second request that waits longer for messages to delivered.
+		nr.NoWait = false
+		nr.Expires = expires
+		req, _ = json.Marshal(nr)
 
-					err = nc.PublishRequest(nms, rply, req)
+		// Since first message was an error we UNSUB (batch+1)
+		// since we are counting it as the first message.
+		err = s.AutoUnsubscribe(batch + 1)
+		if err != nil {
+			return nil, err
+		}
+
+		// Make another request and wait for the messages...
+		err = nc.publish(reqNext, inbox, nil, req)
+		if err != nil {
+			s.Unsubscribe()
+			return nil, err
+		}
+
+		// Try to get the first result again or return the error.
+		select {
+		case firstMsg, ok = <-mch:
+			if !ok {
+				err = s.getNextMsgErr()
+			} else {
+				err = s.processNextMsgDelivered(firstMsg)
+				if err == nil {
+					err = checkMsg(firstMsg)
 				}
 			}
+		case <-ctx.Done():
+			err = checkCtxErr(ctx.Err())
+		}
+		if err != nil {
+			s.Unsubscribe()
+			return nil, err
+		}
+		// Check again if the delivered next message is a status error.
+		err = checkMsg(firstMsg)
+		if err != nil {
+			s.Unsubscribe()
+			return nil, err
+		}
+	} else {
+		// We are receiving messages at this point. Send UNSUB to let
+		// the server clear interest once enough replies are delivered.
+		err = s.AutoUnsubscribe(batch)
+		if err != nil {
+			return nil, err
 		}
 	}
-	// If there is at least a message added to msgs, then need to return OK and no error
-	if err != nil && len(msgs) == 0 {
-		return nil, checkCtxErr(err)
+
+	msgs = append(msgs, firstMsg)
+	for {
+		var (
+			msg *Msg
+			ok  bool
+		)
+		select {
+		case msg, ok = <-mch:
+			if !ok {
+				err = s.getNextMsgErr()
+			} else {
+				err = s.processNextMsgDelivered(msg)
+				if err == nil {
+					err = checkMsg(msg)
+				}
+			}
+		case <-ctx.Done():
+			return msgs, checkCtxErr(err)
+		}
+		if err != nil {
+			// Discard the error which may have been a timeout
+			// or 408 request timeout status from the server,
+			// and just the return delivered messages.
+			break
+		}
+		if msg != nil {
+			msgs = append(msgs, msg)
+		}
+
+		if len(msgs) == batch {
+			// Done!
+			break
+		}
 	}
+
 	return msgs, nil
 }
 
@@ -2054,11 +1909,13 @@ func (m *Msg) checkReply() (*js, *jsSub, error) {
 		return nil, nil, ErrMsgNoReply
 	}
 	sub := m.Sub
+	sub.mu.Lock()
 	if sub.jsi == nil {
+		sub.mu.Unlock()
+
 		// Not using a JS context.
 		return nil, nil, nil
 	}
-	sub.mu.Lock()
 	js := sub.jsi.js
 	jsi := sub.jsi
 	sub.mu.Unlock()
diff --git a/vendor/github.com/nats-io/nats.go/nats.go b/vendor/github.com/nats-io/nats.go/nats.go
index e7b45615..ce8db129 100644
--- a/vendor/github.com/nats-io/nats.go/nats.go
+++ b/vendor/github.com/nats-io/nats.go/nats.go
@@ -154,7 +154,6 @@ var (
 	ErrDeliverSubjectRequired       = errors.New("nats: deliver subject is required")
 	ErrPullSubscribeToPushConsumer  = errors.New("nats: cannot pull subscribe to push based consumer")
 	ErrPullSubscribeRequired        = errors.New("nats: must use pull subscribe to bind to pull based consumer")
-	ErrConsumerNotActive            = errors.New("nats: consumer not active")
 )
 
 func init() {
@@ -507,10 +506,6 @@ type Conn struct {
 	respMux       *Subscription        // A single response subscription
 	respMap       map[string]chan *Msg // Request map for the response msg channels
 	respRand      *rand.Rand           // Used for generating suffix
-
-	// Msg filters for testing.
-	// Protected by subsMu
-	filters map[string]msgFilter
 }
 
 type natsReader struct {
@@ -2569,14 +2564,8 @@ func (nc *Conn) waitForMsgs(s *Subscription) {
 		if !s.closed {
 			s.delivered++
 			delivered = s.delivered
-			if s.jsi != nil {
-				s.jsi.mu.Lock()
-				needCheck := s.jsi.fc && len(s.jsi.fcs) > 0
-				s.jsi.active = true
-				s.jsi.mu.Unlock()
-				if needCheck {
-					s.checkForFlowControlResponse(delivered)
-				}
+			if s.jsi != nil && s.jsi.fc && len(s.jsi.fcs) > 0 {
+				s.checkForFlowControlResponse(delivered)
 			}
 		}
 		s.mu.Unlock()
@@ -2612,32 +2601,6 @@ func (nc *Conn) waitForMsgs(s *Subscription) {
 	s.mu.Unlock()
 }
 
-// Used for debugging and simulating loss for certain tests.
-// Return what is to be used. If we return nil the message will be dropped.
-type msgFilter func(m *Msg) *Msg
-
-func (nc *Conn) addMsgFilter(subject string, filter msgFilter) {
-	nc.subsMu.Lock()
-	defer nc.subsMu.Unlock()
-
-	if nc.filters == nil {
-		nc.filters = make(map[string]msgFilter)
-	}
-	nc.filters[subject] = filter
-}
-
-func (nc *Conn) removeMsgFilter(subject string) {
-	nc.subsMu.Lock()
-	defer nc.subsMu.Unlock()
-
-	if nc.filters != nil {
-		delete(nc.filters, subject)
-		if len(nc.filters) == 0 {
-			nc.filters = nil
-		}
-	}
-}
-
 // processMsg is called by parse and will place the msg on the
 // appropriate channel/pending queue for processing. If the channel is full,
 // or the pending queue is over the pending limits, the connection is
@@ -2652,10 +2615,6 @@ func (nc *Conn) processMsg(data []byte) {
 	// that is itself trying to send data to us.
 	nc.subsMu.RLock()
 	sub := nc.subs[nc.ps.ma.sid]
-	var mf msgFilter
-	if nc.filters != nil {
-		mf = nc.filters[string(nc.ps.ma.subject)]
-	}
 	nc.subsMu.RUnlock()
 
 	if sub == nil {
@@ -2670,11 +2629,8 @@ func (nc *Conn) processMsg(data []byte) {
 	// It's possible that we end-up not using the message, but that's ok.
 
 	// FIXME(dlc): Need to copy, should/can do COW?
-	var msgPayload = data
-	if !nc.ps.msgCopied {
-		msgPayload = make([]byte, len(data))
-		copy(msgPayload, data)
-	}
+	msgPayload := make([]byte, len(data))
+	copy(msgPayload, data)
 
 	// Check if we have headers encoded here.
 	var h Header
@@ -2701,14 +2657,6 @@ func (nc *Conn) processMsg(data []byte) {
 	// FIXME(dlc): Should we recycle these containers?
 	m := &Msg{Header: h, Data: msgPayload, Subject: subj, Reply: reply, Sub: sub}
 
-	// Check for message filters.
-	if mf != nil {
-		if m = mf(m); m == nil {
-			// Drop message.
-			return
-		}
-	}
-
 	sub.mu.Lock()
 
 	// Check if closed.
@@ -2721,11 +2669,6 @@ func (nc *Conn) processMsg(data []byte) {
 	jsi := sub.jsi
 	if jsi != nil {
 		ctrlMsg, hasHBs, hasFC = isControlMessage(m), jsi.hbs, jsi.fc
-		// Check for ordered consumer here. If checkOrdered returns true that means it detected a gap.
-		if jsi.ordered && sub.checkOrderedMsgs(m) {
-			sub.mu.Unlock()
-			return
-		}
 	}
 
 	// Skip processing if this is a control message.
@@ -2777,7 +2720,7 @@ func (nc *Conn) processMsg(data []byte) {
 	} else if hasFC && m.Reply != _EMPTY_ {
 		// This is a flow control message.
 		// If we have no pending, go ahead and send in place.
-		if sub.pMsgs <= 0 {
+		if sub.pMsgs == 0 {
 			nc.Publish(m.Reply, nil)
 		} else {
 			// Schedule a reply after the previous message is delivered.
@@ -2785,13 +2728,14 @@ func (nc *Conn) processMsg(data []byte) {
 		}
 	}
 
-	// Clear any SlowConsumer status.
+	// Clear SlowConsumer status.
 	sub.sc = false
+
 	sub.mu.Unlock()
 
 	// Handle control heartbeat messages.
 	if ctrlMsg && hasHBs && m.Reply == _EMPTY_ {
-		nc.checkForSequenceMismatch(m, sub, jsi)
+		nc.processSequenceMismatch(m, sub, jsi)
 	}
 
 	return
@@ -3154,8 +3098,7 @@ const (
 	lastConsumerSeqHdr = "Nats-Last-Consumer"
 	lastStreamSeqHdr   = "Nats-Last-Stream"
 	noResponders       = "503"
-	noMessagesSts      = "404"
-	reqTimeoutSts      = "408"
+	noMessages         = "404"
 	controlMsg         = "100"
 	statusLen          = 3 // e.g. 20x, 40x, 50x
 )
@@ -3719,7 +3662,7 @@ func (nc *Conn) subscribeLocked(subj, queue string, cb MsgHandler, ch chan *Msg,
 	if badSubject(subj) {
 		return nil, ErrBadSubject
 	}
-	if queue != _EMPTY_ && badQueue(queue) {
+	if queue != "" && badQueue(queue) {
 		return nil, ErrBadQueueName
 	}
 
@@ -3826,12 +3769,6 @@ func (s *Subscription) Type() SubscriptionType {
 	}
 	s.mu.Lock()
 	defer s.mu.Unlock()
-	// Pull subscriptions are really a SyncSubscription and we want this
-	// type to be set internally for all delivered messages management, etc..
-	// So check when to return PullSubscription to the user.
-	if s.jsi != nil && s.jsi.pull {
-		return PullSubscription
-	}
 	return s.typ
 }
 
@@ -3941,22 +3878,12 @@ func (s *Subscription) AutoUnsubscribe(max int) error {
 // unsubscribe performs the low level unsubscribe to the server.
 // Use Subscription.Unsubscribe()
 func (nc *Conn) unsubscribe(sub *Subscription, max int, drainMode bool) error {
-	var maxStr string
-	if max > 0 {
-		sub.mu.Lock()
-		sub.max = uint64(max)
-		if sub.delivered < sub.max {
-			maxStr = strconv.Itoa(max)
-		}
-		sub.mu.Unlock()
-	}
-
 	// For JetStream consumers, need to clean up ephemeral consumers
 	// or delete durable ones if called with Unsubscribe.
 	sub.mu.Lock()
 	jsi := sub.jsi
 	sub.mu.Unlock()
-	if jsi != nil && maxStr == _EMPTY_ {
+	if jsi != nil {
 		err := jsi.unsubscribe(drainMode)
 		if err != nil {
 			return err
@@ -3966,6 +3893,7 @@ func (nc *Conn) unsubscribe(sub *Subscription, max int, drainMode bool) error {
 	nc.mu.Lock()
 	// ok here, but defer is expensive
 	defer nc.mu.Unlock()
+	defer nc.kickFlusher()
 
 	if nc.isClosed() {
 		return ErrConnectionClosed
@@ -3979,7 +3907,13 @@ func (nc *Conn) unsubscribe(sub *Subscription, max int, drainMode bool) error {
 		return nil
 	}
 
-	if maxStr == _EMPTY_ && !drainMode {
+	maxStr := _EMPTY_
+	if max > 0 {
+		s.mu.Lock()
+		s.max = uint64(max)
+		s.mu.Unlock()
+		maxStr = strconv.Itoa(max)
+	} else if !drainMode {
 		nc.removeSub(s)
 	}
 
@@ -4103,14 +4037,8 @@ func (s *Subscription) processNextMsgDelivered(msg *Msg) error {
 	// Update some stats.
 	s.delivered++
 	delivered := s.delivered
-	if s.jsi != nil {
-		s.jsi.mu.Lock()
-		needCheck := s.jsi.fc && len(s.jsi.fcs) > 0
-		s.jsi.active = true
-		s.jsi.mu.Unlock()
-		if needCheck {
-			s.checkForFlowControlResponse(delivered)
-		}
+	if s.jsi != nil && s.jsi.fc && len(s.jsi.fcs) > 0 {
+		s.checkForFlowControlResponse(delivered)
 	}
 
 	if s.typ == SyncSubscription {
diff --git a/vendor/github.com/nats-io/nats.go/parser.go b/vendor/github.com/nats-io/nats.go/parser.go
index f5f6da8e..c9cbfeb6 100644
--- a/vendor/github.com/nats-io/nats.go/parser.go
+++ b/vendor/github.com/nats-io/nats.go/parser.go
@@ -28,15 +28,14 @@ type msgArg struct {
 const MAX_CONTROL_LINE_SIZE = 4096
 
 type parseState struct {
-	state     int
-	as        int
-	drop      int
-	hdr       int
-	ma        msgArg
-	argBuf    []byte
-	msgBuf    []byte
-	msgCopied bool
-	scratch   [MAX_CONTROL_LINE_SIZE]byte
+	state   int
+	as      int
+	drop    int
+	hdr     int
+	ma      msgArg
+	argBuf  []byte
+	msgBuf  []byte
+	scratch [MAX_CONTROL_LINE_SIZE]byte
 }
 
 const (
@@ -168,7 +167,7 @@ func (nc *Conn) parse(buf []byte) error {
 			if nc.ps.msgBuf != nil {
 				if len(nc.ps.msgBuf) >= nc.ps.ma.size {
 					nc.processMsg(nc.ps.msgBuf)
-					nc.ps.argBuf, nc.ps.msgBuf, nc.ps.msgCopied, nc.ps.state = nil, nil, false, MSG_END
+					nc.ps.argBuf, nc.ps.msgBuf, nc.ps.state = nil, nil, MSG_END
 				} else {
 					// copy as much as we can to the buffer and skip ahead.
 					toCopy := nc.ps.ma.size - len(nc.ps.msgBuf)
@@ -191,7 +190,7 @@ func (nc *Conn) parse(buf []byte) error {
 				}
 			} else if i-nc.ps.as >= nc.ps.ma.size {
 				nc.processMsg(buf[nc.ps.as:i])
-				nc.ps.argBuf, nc.ps.msgBuf, nc.ps.msgCopied, nc.ps.state = nil, nil, false, MSG_END
+				nc.ps.argBuf, nc.ps.msgBuf, nc.ps.state = nil, nil, MSG_END
 			}
 		case MSG_END:
 			switch b {
@@ -404,7 +403,6 @@ func (nc *Conn) parse(buf []byte) error {
 
 			nc.ps.msgBuf = make([]byte, lrem, nc.ps.ma.size)
 			copy(nc.ps.msgBuf, buf[nc.ps.as:])
-			nc.ps.msgCopied = true
 		} else {
 			nc.ps.msgBuf = nc.ps.scratch[len(nc.ps.argBuf):len(nc.ps.argBuf)]
 			nc.ps.msgBuf = append(nc.ps.msgBuf, (buf[nc.ps.as:])...)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 8f2fdc9a..87318715 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -9,7 +9,7 @@ github.com/minio/highwayhash
 # github.com/nats-io/jwt/v2 v2.0.3
 ## explicit
 github.com/nats-io/jwt/v2
-# github.com/nats-io/nats.go v1.11.1-0.20210810010129-d1955c8653ca
+# github.com/nats-io/nats.go v1.11.1-0.20210803204434-91bdffe39f41
 ## explicit
 github.com/nats-io/nats.go
 github.com/nats-io/nats.go/encoders/builtin


Test patch:
diff --git a/server/jetstream_cluster_test.go b/server/jetstream_cluster_test.go
index 7e6aee2c..2ae97422 100644
--- a/server/jetstream_cluster_test.go
+++ b/server/jetstream_cluster_test.go
@@ -4893,7 +4893,8 @@ func TestJetStreamCrossAccountMirrorsAndSources(t *testing.T) {
 		t.Fatalf("Unexpected error: %v", err)
 	}
 
-	toSend := 100
+	// use large number to tease out FC issues
+	toSend := 3000
 	for i := 0; i < toSend; i++ {
 		if _, err := js.Publish("TEST", []byte("OK")); err != nil {
 			t.Fatalf("Unexpected publish error: %v", err)
@@ -8193,6 +8194,7 @@ var jsClusterMirrorSourceImportsTempl = `
 			exports [
 				{ service: "$JS.API.CONSUMER.>" } # To create internal consumers to mirror/source.
 				{ stream: "RI.DELIVER.SYNC.>" }   # For the mirror/source consumers sending to IA via delivery subject.
+				{ service: "$JS.FC.>" }
 			]
 		}
 		IA {
@@ -8201,6 +8203,7 @@ var jsClusterMirrorSourceImportsTempl = `
 			imports [
 				{ service: { account: JS, subject: "$JS.API.CONSUMER.>"}, to: "RI.JS.API.CONSUMER.>" }
 				{ stream: { account: JS, subject: "RI.DELIVER.SYNC.>"} }
+				{ service: {account: JS, subject: "$JS.FC.>" }}
 			]
 		}
 		$SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] }
diff --git a/server/jetstream_errors_test.go b/server/jetstream_errors_test.go
index c7adcee3..95ec8e79 100644
--- a/server/jetstream_errors_test.go
+++ b/server/jetstream_errors_test.go
@@ -2,7 +2,9 @@ package server
 
 import (
 	"errors"
+	"fmt"
 	"testing"
+	"time"
 )
 
 func TestIsNatsErr(t *testing.T) {
@@ -45,8 +47,8 @@ func TestApiError_Error(t *testing.T) {
 	}
 }
 
-func TestApiError_NewWithTags(t *testing.T) {
-	ne := NewJSRestoreSubscribeFailedError(errors.New("failed error"), "the.subject")
+func TestApiError_NewT(t *testing.T) {
+	ne := ApiErrors[JSRestoreSubscribeFailedErrF].NewT("{subject}", "the.subject", "{err}", errors.New("failed error"))
 	if ne.Description != "JetStream unable to subscribe to restore snapshot the.subject: failed error" {
 		t.Fatalf("Expected 'JetStream unable to subscribe to restore snapshot the.subject: failed error' got %q", ne.Description)
 	}
@@ -54,30 +56,48 @@ func TestApiError_NewWithTags(t *testing.T) {
 	if ne == ApiErrors[JSRestoreSubscribeFailedErrF] {
 		t.Fatalf("Expected a new instance")
 	}
+
+	aerr := ApiError{
+		Code:        999,
+		Description: "thing {string} failed on attempt {int} after {duration} with {float}: {err}",
+	}
+
+	if ne := aerr.NewT("{float}", 1.1, "{err}", fmt.Errorf("simulated error"), "{string}", "hello world", "{int}", 10, "{duration}", 456*time.Millisecond); ne.Description != "thing hello world failed on attempt 10 after 456ms with 1.1: simulated error" {
+		t.Fatalf("Expected formatted error, got: %q", ne.Description)
+	}
 }
 
-func TestApiError_NewWithUnless(t *testing.T) {
-	if ne := NewJSStreamRestoreError(errors.New("failed error"), Unless(ApiErrors[JSNotEnabledForAccountErr])); !IsNatsErr(ne, JSNotEnabledForAccountErr) {
+func TestApiError_ErrOrNewT(t *testing.T) {
+	if ne := ApiErrors[JSStreamRestoreErrF].ErrOrNewT(ApiErrors[JSNotEnabledForAccountErr], "{err}", errors.New("failed error")); !IsNatsErr(ne, JSNotEnabledForAccountErr) {
 		t.Fatalf("Expected JSNotEnabledForAccountErr got %s", ne)
 	}
 
-	if ne := NewJSStreamRestoreError(errors.New("failed error")); !IsNatsErr(ne, JSStreamRestoreErrF) {
+	if ne := ApiErrors[JSStreamRestoreErrF].ErrOrNewT(nil, "{err}", errors.New("failed error")); !IsNatsErr(ne, JSStreamRestoreErrF) {
 		t.Fatalf("Expected JSStreamRestoreErrF got %s", ne)
 	}
 
-	if ne := NewJSStreamRestoreError(errors.New("failed error"), Unless(errors.New("other error"))); !IsNatsErr(ne, JSStreamRestoreErrF) {
+	if ne := ApiErrors[JSStreamRestoreErrF].ErrOrNewT(errors.New("other error"), "{err}", errors.New("failed error")); !IsNatsErr(ne, JSStreamRestoreErrF) {
 		t.Fatalf("Expected JSStreamRestoreErrF got %s", ne)
 	}
 
-	if ne := NewJSPeerRemapError(Unless(ApiErrors[JSNotEnabledForAccountErr])); !IsNatsErr(ne, JSNotEnabledForAccountErr) {
+	// ensure that mistakenly passing a non tagged error to this function is harmless
+	if ne := ApiErrors[JSStreamNotFoundErr].ErrOrNewT(errors.New("other error"), "{err}", errors.New("failed error")); !IsNatsErr(ne, JSStreamNotFoundErr) {
+		t.Fatalf("Expected JSStreamNotFoundErr got %s", ne)
+	} else if ne.Description != ApiErrors[JSStreamNotFoundErr].Description {
+		t.Fatalf("Expected JSStreamNotFoundErr description got: %s", ne.Description)
+	}
+}
+
+func TestApiError_ErrOr(t *testing.T) {
+	if ne := ApiErrors[JSPeerRemapErr].ErrOr(ApiErrors[JSNotEnabledForAccountErr]); !IsNatsErr(ne, JSNotEnabledForAccountErr) {
 		t.Fatalf("Expected JSNotEnabledForAccountErr got %s", ne)
 	}
 
-	if ne := NewJSPeerRemapError(Unless(nil)); !IsNatsErr(ne, JSPeerRemapErr) {
+	if ne := ApiErrors[JSPeerRemapErr].ErrOr(nil); !IsNatsErr(ne, JSPeerRemapErr) {
 		t.Fatalf("Expected JSPeerRemapErr got %s", ne)
 	}
 
-	if ne := NewJSPeerRemapError(Unless(errors.New("other error"))); !IsNatsErr(ne, JSPeerRemapErr) {
+	if ne := ApiErrors[JSPeerRemapErr].ErrOr(errors.New("other error")); !IsNatsErr(ne, JSPeerRemapErr) {
 		t.Fatalf("Expected JSPeerRemapErr got %s", ne)
 	}
 }
diff --git a/server/jetstream_test.go b/server/jetstream_test.go
index 0acd0f12..3264b5e1 100644
--- a/server/jetstream_test.go
+++ b/server/jetstream_test.go
@@ -12551,70 +12551,6 @@ func TestJetStreamConsumerPendingBugWithKV(t *testing.T) {
 	}
 }
 
-// Issue #2420
-func TestJetStreamDefaultMaxMsgsPer(t *testing.T) {
-	s := RunBasicJetStreamServer()
-	defer s.Shutdown()
-
-	if config := s.JetStreamConfig(); config != nil {
-		defer removeDir(t, config.StoreDir)
-	}
-
-	// Client for API requests.
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	si, err := js.AddStream(&nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo.*"},
-		Storage:  nats.MemoryStorage,
-		MaxMsgs:  10,
-	})
-	if err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-	if si.Config.MaxMsgsPerSubject != -1 {
-		t.Fatalf("Expected default of -1, got %d", si.Config.MaxMsgsPerSubject)
-	}
-}
-
-// Issue #2423
-func TestJetStreamBadConsumerCreateErr(t *testing.T) {
-	s := RunBasicJetStreamServer()
-	defer s.Shutdown()
-
-	if config := s.JetStreamConfig(); config != nil {
-		defer removeDir(t, config.StoreDir)
-	}
-
-	// Client for API requests.
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo.*"},
-		Storage:  nats.MemoryStorage,
-	})
-	if err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-
-	// When adding a consumer with both deliver subject and max wait (push vs pull),
-	// we got the wrong err about deliver subject having a wildcard.
-	_, err = js.AddConsumer("TEST", &nats.ConsumerConfig{
-		Durable:        "nowcerr",
-		DeliverSubject: "X",
-		MaxWaiting:     100,
-	})
-	if err == nil {
-		t.Fatalf("Expected an error but got none")
-	}
-	if !strings.Contains(err.Error(), "push mode can not set max waiting") {
-		t.Fatalf("Incorrect error returned: %v", err)
-	}
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Simple JetStream Benchmarks
 ///////////////////////////////////////////////////////////////////////////
diff --git a/server/norace_test.go b/server/norace_test.go
index 65b2f5b2..a948126b 100644
--- a/server/norace_test.go
+++ b/server/norace_test.go
@@ -2486,65 +2486,3 @@ func TestNoRaceJetStreamSlowRestartWithManyExpiredMsgs(t *testing.T) {
 		t.Fatalf("Expected no msgs after restart, got %d", si.State.Msgs)
 	}
 }
-
-func TestNoRaceJetStreamStalledMirrorsAfterExpire(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	cfg := &nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo.*"},
-		Replicas: 1,
-		MaxAge:   250 * time.Microsecond,
-	}
-
-	if _, err := js.AddStream(cfg); err != nil {
-		t.Fatalf("Error creating stream: %v", err)
-	}
-
-	if _, err := js.AddStream(&nats.StreamConfig{
-		Name:     "M",
-		Replicas: 2,
-		Mirror:   &nats.StreamSource{Name: "TEST"},
-	}); err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-
-	sendBatch := func(batch int) {
-		t.Helper()
-		for i := 0; i < batch; i++ {
-			js.PublishAsync("foo.bar", []byte("Hello"))
-		}
-		select {
-		case <-js.PublishAsyncComplete():
-		case <-time.After(5 * time.Second):
-			t.Fatalf("Did not receive completion signal")
-		}
-	}
-
-	numMsgs := 25_000
-	sendBatch(numMsgs)
-
-	// Turn off expiration so we can test we did not stall.
-	cfg.MaxAge = 0
-	if _, err := js.UpdateStream(cfg); err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-
-	sendBatch(numMsgs)
-
-	// Wait for mirror to be caught up.
-	checkFor(t, 5*time.Second, 500*time.Millisecond, func() error {
-		si, err := js.StreamInfo("M")
-		if err != nil {
-			t.Fatalf("Unexpected error: %v", err)
-		}
-		if si.State.LastSeq != uint64(2*numMsgs) {
-			return fmt.Errorf("Expected %d as last sequence, got state: %+v", 2*numMsgs, si.State)
-		}
-		return nil
-	})
-}
diff --git a/vendor/github.com/nats-io/nats.go/go_test.mod b/vendor/github.com/nats-io/nats.go/go_test.mod
index a0a0b93b..3c47e812 100644
--- a/vendor/github.com/nats-io/nats.go/go_test.mod
+++ b/vendor/github.com/nats-io/nats.go/go_test.mod
@@ -1,10 +1,10 @@
 module github.com/nats-io/nats.go
 
-go 1.16
+go 1.15
 
 require (
 	github.com/golang/protobuf v1.4.2
-	github.com/nats-io/nats-server/v2 v2.3.4
+	github.com/nats-io/nats-server/v2 v2.2.7-0.20210618192106-93a3720475a4
 	github.com/nats-io/nkeys v0.3.0
 	github.com/nats-io/nuid v1.0.1
 	google.golang.org/protobuf v1.23.0
diff --git a/vendor/github.com/nats-io/nats.go/go_test.sum b/vendor/github.com/nats-io/nats.go/go_test.sum
index 5997e883..09550633 100644
--- a/vendor/github.com/nats-io/nats.go/go_test.sum
+++ b/vendor/github.com/nats-io/nats.go/go_test.sum
@@ -15,11 +15,15 @@ github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz
 github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
 github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU=
 github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
-github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI=
-github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
-github.com/nats-io/nats-server/v2 v2.3.4 h1:WcNa6HDFX8gjZPHb8CJ9wxRHEjJSlhWUb/MKb6/mlUY=
-github.com/nats-io/nats-server/v2 v2.3.4/go.mod h1:3mtbaN5GkCo/Z5T3nNj0I0/W1fPkKzLiDC6jjWJKp98=
-github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
+github.com/nats-io/jwt/v2 v2.0.2 h1:ejVCLO8gu6/4bOKIHQpmB5UhhUJfAQw55yvLWpfmKjI=
+github.com/nats-io/jwt/v2 v2.0.2/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
+github.com/nats-io/nats-server/v2 v2.2.6 h1:FPK9wWx9pagxcw14s8W9rlfzfyHm61uNLnJyybZbn48=
+github.com/nats-io/nats-server/v2 v2.2.6/go.mod h1:sEnFaxqe09cDmfMgACxZbziXnhQFhwk+aKkZjBBRYrI=
+github.com/nats-io/nats-server/v2 v2.2.7-0.20210615172038-0069f752b61b h1:hy5rgG4Hur55cWBKxD/VbkjaRYYAxo5Ayk9AxGJcHTs=
+github.com/nats-io/nats-server/v2 v2.2.7-0.20210615172038-0069f752b61b/go.mod h1:hBgcnXvNESvh65J1nMtxaHHsaUxSmteZXCH1JLTuvfg=
+github.com/nats-io/nats-server/v2 v2.2.7-0.20210618192106-93a3720475a4 h1:8QM5O7j1a9SdEPzzpQj7daRu4fi/sxfXRxfcKGa5Dr0=
+github.com/nats-io/nats-server/v2 v2.2.7-0.20210618192106-93a3720475a4/go.mod h1:hBgcnXvNESvh65J1nMtxaHHsaUxSmteZXCH1JLTuvfg=
+github.com/nats-io/nats.go v1.11.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
@@ -27,17 +31,17 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
-golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210505212654-3497b51f5e64 h1:QuAh/1Gwc0d+u9walMU1NqzhRemNegsv5esp2ALQIY4=
+golang.org/x/crypto v0.0.0-20210505212654-3497b51f5e64/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=