nats-io/nats-server · error

message overrun

Error message

message overrun

What it means

Thrown during block load/recovery while scanning the raw message buffer: the scan position plus the fixed message header size (msgHdrSize) extends past the buffer end, meaning a truncated or partial header was found. The store rejects the block content rather than parsing a corrupt record.

Source

Thrown at server/filestore.go:6482

	buf := mb.cache.buf
	nbuf := getMsgBlockBuf(len(buf))
	// Recycle our nbuf when we are done.
	defer recycleMsgBlockBuf(nbuf)

	var le = binary.LittleEndian
	var firstSet bool
	var last uint64
	var msgs uint64

	fseq := atomic.LoadUint64(&mb.first.seq)
	lseq := atomic.LoadUint64(&mb.last.seq)
	isDeleted := func(seq uint64) bool {
		return seq == 0 || seq&ebit != 0 || mb.dmap.Exists(seq) || seq < fseq
	}

	for index, lbuf := uint32(0), uint32(len(buf)); index < lbuf; {
		if index+msgHdrSize > lbuf {
			return fmt.Errorf("message overrun")
		}
		hdr := buf[index : index+msgHdrSize]
		rl, slen := le.Uint32(hdr[0:]), int(le.Uint16(hdr[20:]))
		hasHeaders := rl&hbit != 0
		// Clear any headers bit that could be set.
		rl &^= hbit
		shlen := slen
		if hasHeaders {
			shlen += 4
		}
		dlen := int(rl) - msgHdrSize
		// Do some quick sanity checks here.
		if dlen < 0 || shlen > (dlen-recordHashSize) || dlen > int(rl) || index+rl > lbuf || rl > rlBadThresh {
			return fmt.Errorf("sanity check failed")
		}
		// Only need to process non-deleted messages.
		seq := le.Uint64(hdr[4:])
		ts := int64(le.Uint64(hdr[12:]))

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Stop the server and run the JetStream file-store consistency checker / reset the affected stream (delete stream files so it re-creates)
  2. Restore the store directory from a consistent backup taken while the server was stopped
  3. Never copy or rsync live JetStream data directories; take snapshots offline
  4. Check the underlying filesystem/disk for corruption (fsck, SMART)
Defensive patterns

Strategy: validation

Validate before calling

// Before restart/recovery, ensure store files were not copied or truncated live:
// 1) stop the server, 2) verify file sizes match metadata, 3) back up before recovery.
// There is no pre-call API check; guard the environment instead.

Try / catch

// Go: on recovery error, reset the affected stream rather than retrying
if err := recoverStream(storeDir, streamName); err != nil {
    if strings.Contains(err.Error(), "message overrun") {
        // block file truncated: restore backup or reset stream
    }
    return err
}

Prevention

When it happens

Trigger: Recovering a message block whose file was truncated mid-header (crash before flush, partial write, or externally truncated file) so len(buf) - index < msgHdrSize.

Common situations: Power loss / kill -9 without fsync landing, copying store files while the server is running, restore from an inconsistent backup, disk corruption.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/8cff224f000c2aa9. Report an issue: GitHub.