nats-io/nats-server · error · JSStreamHeaderExceedsMaximumError
10097
10097
Error message
JetStream header size exceeds limits for '%s > %s'
What it means
JetStream message header size limit error (JSStreamHeaderExceedsMaximumError, code 10097). NATS encodes header lengths as uint16, so headers must fit in 65535 bytes; batches or counter messages with oversized headers are rejected pre-proposal to avoid downstream corruption.
Source
Thrown at server/jetstream_batching.go:551
diff *batchStagedDiff, mset *stream, subject, rsubject string, hdr []byte, msg []byte, sourced bool, name string,
jsa *jsAccount, allowRollup, denyPurge, allowTTL, allowMsgCounter, allowMsgSchedules bool,
discard DiscardPolicy, discardNewPer bool, maxMsgSize int, maxMsgs int64, maxMsgsPer int64, maxBytes int64,
) ([]byte, []byte, uint64, *ApiError, error) {
var incr *big.Int
var hasSchedule bool
// Do this before staging any proposal state. All clustered publish paths,
// including atomic and fast batches, use this helper.
if mset.store.Type() == FileStorage && isFileStoreMsgTooLarge(fileStoreMsgSize(subject, hdr, msg)) {
return hdr, msg, 0, NewJSStreamStoreFailedError(ErrMsgTooLarge), ErrMsgTooLarge
}
// Some header checks must be checked pre proposal.
if len(hdr) > 0 {
// Since we encode header len as u16 make sure we do not exceed.
// Again this works if it goes through but better to be pre-emptive.
if len(hdr) > math.MaxUint16 {
err := fmt.Errorf("JetStream header size exceeds limits for '%s > %s'", jsa.acc().Name, name)
return hdr, msg, 0, NewJSStreamHeaderExceedsMaximumError(), err
}
// Counter increments.
// Only supported on counter streams, and payload must be empty (if not coming from a source).
var ok bool
if incr, ok = getMessageIncr(hdr); !ok {
apiErr := NewJSMessageIncrInvalidError()
return hdr, msg, 0, apiErr, apiErr
} else if incr != nil && !sourced {
// Only do checks if the message isn't sourced. Otherwise, we need to store verbatim.
if !allowMsgCounter {
apiErr := NewJSMessageIncrDisabledError()
return hdr, msg, 0, apiErr, apiErr
} else if len(msg) > 0 {
apiErr := NewJSMessageIncrPayloadError()
return hdr, msg, 0, apiErr, apiErr
} else {
// Check for incompatible headers.View on GitHub (pinned to 3a66a489d2)
Solutions
- Reduce header size: trim or consolidate user headers to stay under 65535 bytes
- Move large metadata into the message payload instead of headers
- Split oversized atomic/fast batches into smaller batches so per-message headers fit
Example fix
// before
hdr := nats.Header{}
for i := 0; i < 5000; i++ { hdr.Add(fmt.Sprintf("X-Trace-%d", i), bigValue) }
// after
if hdrEncoded := encodeHeaders(hdr); len(hdrEncoded) > math.MaxUint16 {
hdr = pruneLargeHeaders(hdr) // keep under 65535 bytes
} Defensive patterns
Strategy: validation
Validate before calling
const maxHeader = math.MaxUint16
if h := encodedHeaderLen(hdr); h > maxHeader {
return fmt.Errorf("header size %d exceeds %d", h, maxHeader)
} Type guard
func headersWithinLimit(hdr nats.Header) bool {
return encodedHeaderLen(hdr) <= math.MaxUint16
} Try / catch
_, err := js.PublishMsg(msg)
var he *nats.APIError
if errors.As(err, &he) && he.ErrorCode == 10097 {
msg.Header = pruneHeaders(msg.Header)
_, err = js.PublishMsg(msg)
} Prevention
- Keep per-message headers small; move bulk metadata to payload
- Split batches so accumulated headers stay under 65535 bytes
- Test pipelines that copy headers between sourced messages
When it happens
Trigger: Publishing a message (or atomic/fast batch entry, including counter increment messages) to a JetStream stream whose headers total more than math.MaxUint16 (65535) bytes.
Common situations: Accumulating very large header sets (many Nats-Msg-Id dedup or user headers); batch protocols appending headers per entry until the u16 limit overflows; source/transform pipelines copying headers between messages.
Related errors
- error creating store for stream
- error creating store for consumer
- JS_STREAM_OFFLINE
- JS_ERR_GENERIC
- JS_STREAM_WRONG_LAST_SEQUENCE
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/9fd1813278200684.
Report an issue: GitHub.