nats-io/nats-server · warning
JetStream message size exceeds limits for '%s > %s'
Error message
JetStream message size exceeds limits for '%s > %s'
What it means
During JetStream publish routing, the server pre-emptively checks incoming messages against the stream's MaxMsgSize (falling back to account/server max payload limits). If the header or payload length exceeds the limit, it logs 'JetStream message size exceeds limits for <account > stream>' and returns JSStreamMessageExceedsMaximumError to the publisher instead of letting the message flow through and fail later.
Source
Thrown at server/jetstream_cluster.go:12123
// Check here pre-emptively if we have exceeded our account limits.
if exceeded, err := jsa.wouldExceedLimits(st, tierName, r, csubject, hdr, msg); exceeded {
if err == nil {
err = NewJSAccountResourcesExceededError()
}
s.RateLimitWarnf("JetStream account limits exceeded for '%s': %s", jsa.acc().GetName(), err.Error())
if canRespond {
var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}
resp.Error = err
response, _ = json.Marshal(resp)
outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))
}
return err
}
// Check msgSize if we have a limit set there. Again this works if it goes through but better to be pre-emptive.
// Subtract to prevent against overflows.
if maxMsgSize >= 0 && (len(hdr) > maxMsgSize || len(msg) > maxMsgSize-len(hdr)) {
err := fmt.Errorf("JetStream message size exceeds limits for '%s > %s'", jsa.acc().Name, name)
s.RateLimitWarnf("%s", err.Error())
if canRespond {
var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}
resp.Error = NewJSStreamMessageExceedsMaximumError()
response, _ = json.Marshal(resp)
outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))
}
return err
}
// Proceed with proposing this message.
// We only use mset.clseq for clustering and in case we run ahead of actual commits.
// Check if we need to set initial value here
mset.clMu.Lock()
if mset.clseq == 0 || mset.clseq < lseq+mset.clfs {
lseq = recalculateClusteredSeq(mset, true)
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Reduce message size: split or compress the payload before publishing.
- Raise the stream's MaxMsgSize via stream update (still bounded by server max_payload).
- Raise the server's max_payload in nats.conf if the limit originates there (requires cluster-wide consistent value and restart).
- Check client-side with len(data) + header size before publishing to fail fast.
Example fix
// before
js.Publish("ORDERS.new", bigPayload) // > MaxMsgSize
// after
if len(bigPayload) > maxAllowed {
bigPayload = compress(bigPayload) // or chunk and publish parts
}
js.Publish("ORDERS.new", bigPayload) Defensive patterns
Strategy: validation
Validate before calling
// Go client: pre-check size before publishing
info, _ := js.StreamInfo(streamName)
maxAllowed := int(info.Config.MaxMsgSize)
if maxAllowed >= 0 && len(msg)+len(hdr) > maxAllowed {
return fmt.Errorf("payload %d exceeds stream max %d", len(msg), maxAllowed)
} Try / catch
ak, err := js.Publish(subj, payload)
var apiErr *nats.APIError
if errors.As(err, &apiErr) && apiErr.ErrorCode == 10059 { // exceeds max
payload = chunkOrCompress(payload)
ak, err = js.Publish(subj, payload)
} Prevention
- Match producer payload sizes to the stream MaxMsgSize during design.
- Enable client-side chunking for large payloads (JetStream object store handles this).
- Keep max_payload consistent across the cluster and note it constrains MaxMsgSize.
- Subscribe to the RateLimitWarnf symptom in monitoring for repeated violations.
When it happens
Trigger: Publishing a message (with `js.Publish`, `nc.Request` to a stream-mapped subject, or direct raw publish) whose total size (headers included) exceeds the stream's MaxMsgSize or the server's max_payload; the check is len(msg) > maxMsgSize - len(hdr), so large headers alone can trip it.
Common situations: Producers sending attachments or batched payloads larger than the configured limit; a stream created with a tighter MaxMsgSize than the server default; base64/JSON envelopes inflating payloads past the limit.
Related errors
- system limit reached
- 10071
- 10069
- duplicate window limits are higher than current limits
- change to limits violates consumers: %s
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/9b187c6327a68f47.
Report an issue: GitHub.