{"record":{"id":"8cff224f000c2aa9","repo":"nats-io/nats-server","slug":"message-overrun","errorCode":null,"errorMessage":"message overrun","messagePattern":"message overrun","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/filestore.go","lineNumber":6482,"sourceCode":"\tbuf := mb.cache.buf\n\tnbuf := getMsgBlockBuf(len(buf))\n\t// Recycle our nbuf when we are done.\n\tdefer recycleMsgBlockBuf(nbuf)\n\n\tvar le = binary.LittleEndian\n\tvar firstSet bool\n\tvar last uint64\n\tvar msgs uint64\n\n\tfseq := atomic.LoadUint64(&mb.first.seq)\n\tlseq := atomic.LoadUint64(&mb.last.seq)\n\tisDeleted := func(seq uint64) bool {\n\t\treturn seq == 0 || seq&ebit != 0 || mb.dmap.Exists(seq) || seq < fseq\n\t}\n\n\tfor index, lbuf := uint32(0), uint32(len(buf)); index < lbuf; {\n\t\tif index+msgHdrSize > lbuf {\n\t\t\treturn fmt.Errorf(\"message overrun\")\n\t\t}\n\t\thdr := buf[index : index+msgHdrSize]\n\t\trl, slen := le.Uint32(hdr[0:]), int(le.Uint16(hdr[20:]))\n\t\thasHeaders := rl&hbit != 0\n\t\t// Clear any headers bit that could be set.\n\t\trl &^= hbit\n\t\tshlen := slen\n\t\tif hasHeaders {\n\t\t\tshlen += 4\n\t\t}\n\t\tdlen := int(rl) - msgHdrSize\n\t\t// Do some quick sanity checks here.\n\t\tif dlen < 0 || shlen > (dlen-recordHashSize) || dlen > int(rl) || index+rl > lbuf || rl > rlBadThresh {\n\t\t\treturn fmt.Errorf(\"sanity check failed\")\n\t\t}\n\t\t// Only need to process non-deleted messages.\n\t\tseq := le.Uint64(hdr[4:])\n\t\tts := int64(le.Uint64(hdr[12:]))","sourceCodeStart":6464,"sourceCodeEnd":6500,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/filestore.go#L6464-L6500","documentation":"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.","triggerScenarios":"Recovering a message block whose file was truncated mid-header (crash before flush, partial write, or externally truncated file) so len(buf) - index < msgHdrSize.","commonSituations":"Power loss / kill -9 without fsync landing, copying store files while the server is running, restore from an inconsistent backup, disk corruption.","solutions":["Stop the server and run the JetStream file-store consistency checker / reset the affected stream (delete stream files so it re-creates)","Restore the store directory from a consistent backup taken while the server was stopped","Never copy or rsync live JetStream data directories; take snapshots offline","Check the underlying filesystem/disk for corruption (fsck, SMART)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before restart/recovery, ensure store files were not copied or truncated live:\n// 1) stop the server, 2) verify file sizes match metadata, 3) back up before recovery.\n// There is no pre-call API check; guard the environment instead.","typeGuard":null,"tryCatchPattern":"// Go: on recovery error, reset the affected stream rather than retrying\nif err := recoverStream(storeDir, streamName); err != nil {\n    if strings.Contains(err.Error(), \"message overrun\") {\n        // block file truncated: restore backup or reset stream\n    }\n    return err\n}","preventionTips":["Never copy/rsync live JetStream data directories","Shut down cleanly; avoid kill -9 on jetstream nodes","Use fsync-friendly storage and UPS to survive power loss","Take backups only while the server is stopped"],"tags":["corruption","recovery","filestore"],"backgroundTag":"message-block-corruption","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}