{"record":{"id":"9b187c6327a68f47","repo":"nats-io/nats-server","slug":"jetstream-message-size-exceeds-limits-for-s-s","errorCode":null,"errorMessage":"JetStream message size exceeds limits for '%s > %s'","messagePattern":"JetStream message size exceeds limits for '(.+?) > (.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/jetstream_cluster.go","lineNumber":12123,"sourceCode":"\t// Check here pre-emptively if we have exceeded our account limits.\n\tif exceeded, err := jsa.wouldExceedLimits(st, tierName, r, csubject, hdr, msg); exceeded {\n\t\tif err == nil {\n\t\t\terr = NewJSAccountResourcesExceededError()\n\t\t}\n\t\ts.RateLimitWarnf(\"JetStream account limits exceeded for '%s': %s\", jsa.acc().GetName(), err.Error())\n\t\tif canRespond {\n\t\t\tvar resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}\n\t\t\tresp.Error = err\n\t\t\tresponse, _ = json.Marshal(resp)\n\t\t\toutq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))\n\t\t}\n\t\treturn err\n\t}\n\n\t// Check msgSize if we have a limit set there. Again this works if it goes through but better to be pre-emptive.\n\t// Subtract to prevent against overflows.\n\tif maxMsgSize >= 0 && (len(hdr) > maxMsgSize || len(msg) > maxMsgSize-len(hdr)) {\n\t\terr := fmt.Errorf(\"JetStream message size exceeds limits for '%s > %s'\", jsa.acc().Name, name)\n\t\ts.RateLimitWarnf(\"%s\", err.Error())\n\t\tif canRespond {\n\t\t\tvar resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}}\n\t\t\tresp.Error = NewJSStreamMessageExceedsMaximumError()\n\t\t\tresponse, _ = json.Marshal(resp)\n\t\t\toutq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))\n\t\t}\n\t\treturn err\n\t}\n\n\t// Proceed with proposing this message.\n\n\t// We only use mset.clseq for clustering and in case we run ahead of actual commits.\n\t// Check if we need to set initial value here\n\tmset.clMu.Lock()\n\tif mset.clseq == 0 || mset.clseq < lseq+mset.clfs {\n\t\tlseq = recalculateClusteredSeq(mset, true)\n\t}","sourceCodeStart":12105,"sourceCodeEnd":12141,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_cluster.go#L12105-L12141","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\njs.Publish(\"ORDERS.new\", bigPayload) // > MaxMsgSize\n// after\nif len(bigPayload) > maxAllowed {\n    bigPayload = compress(bigPayload) // or chunk and publish parts\n}\njs.Publish(\"ORDERS.new\", bigPayload)","handlingStrategy":"validation","validationCode":"// Go client: pre-check size before publishing\ninfo, _ := js.StreamInfo(streamName)\nmaxAllowed := int(info.Config.MaxMsgSize)\nif maxAllowed >= 0 && len(msg)+len(hdr) > maxAllowed {\n    return fmt.Errorf(\"payload %d exceeds stream max %d\", len(msg), maxAllowed)\n}","typeGuard":null,"tryCatchPattern":"ak, err := js.Publish(subj, payload)\nvar apiErr *nats.APIError\nif errors.As(err, &apiErr) && apiErr.ErrorCode == 10059 { // exceeds max\n    payload = chunkOrCompress(payload)\n    ak, err = js.Publish(subj, payload)\n}","preventionTips":["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."],"tags":["jetstream","publish","message-size","limits"],"backgroundTag":"message-exceeds-size-limit","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}