nats-io/nats-server · error
failed to parse message sequence %d: invalid header length
Error message
failed to parse message sequence %d: invalid header length
What it means
RestoreStreamV2 reads each backed-up message sequence from the restore reader and validates the per-message block before storing it. This error means the block's declared header size (hdr.HeaderSize) is larger than the actual bytes read for that message block, so the header cannot be extracted from the payload buffer. It indicates a corrupt or malformed stream backup file where the message block layout does not match what was written.
Source
Thrown at server/stream_backup.go:507
storedSizeRaw = fileStoreMsgSizeRaw(len(hdr.Name), int(hdr.HeaderSize), int(hdr.PayloadSize))
}
if storedSizeRaw > math.MaxInt64 {
return nil, fmt.Errorf("snapshot message bytes exceed reserved restore size")
}
storedSize := int64(storedSizeRaw)
if additional := storedSize - restoreRemaining; additional > 0 {
jsa.updateUsage(tier, cfg.Storage, additional)
restoreRemaining += additional
if err := checkUsageLimits(); err != nil {
return nil, err
}
}
buf, err := io.ReadAll(tr)
if err != nil {
return nil, fmt.Errorf("failed to read message sequence %d: %w", seq, err)
}
if hdr.HeaderSize > int64(len(buf)) {
return nil, fmt.Errorf("failed to parse message sequence %d: invalid header length", seq)
}
if int64(len(buf)) != declaredSize {
return nil, fmt.Errorf("failed to read message sequence %d: unexpected payload size", seq)
}
subj := hdr.Name
mhdr := buf[:hdr.HeaderSize]
msg := buf[hdr.HeaderSize : hdr.HeaderSize+hdr.PayloadSize]
if seq <= lseq {
return nil, fmt.Errorf("message sequence %d out of order", seq)
}
// We could have deleted messages since the last message we stored, if so
// we should work out what the gap is and skip those sequences.
if gap := seq - lseq - 1; gap > 0 {
if err := store.SkipMsgs(lseq+1, gap); err != nil {
return nil, fmt.Errorf("failed to process gap: %w", err)
}
}
lseq = seqView on GitHub (pinned to 3a66a489d2)
Solutions
- Verify the backup file integrity (checksum) and re-transfer/re-create the backup from the source stream
- Confirm the backup was created with the same or compatible nats-server version that supports the v2 backup format
- Check that the transfer pipeline (compression, proxies) did not truncate or modify the file byte-for-byte
- Retry the restore with the original unmodified backup archive
Defensive patterns
Strategy: validation
Validate before calling
info, err := fi.Stat()
if err != nil || info.Size() < expectedMinSize { return fmt.Errorf("backup file too small or unreadable") }
// verify checksum against the value recorded at backup time
if got := sha256File(path); got != wantChecksum { return fmt.Errorf("backup checksum mismatch") } Try / catch
mset, err := srv.RestoreStreamV2(...)
if err != nil && strings.Contains(err.Error(), "invalid header length") {
// treat as corrupt backup: do not retry with same file
} Prevention
- Checksum backup files at creation and verify before restore
- Transfer backups in binary-safe modes only
- Never edit or recompress backup archives
- Use matching nats-server versions for backup and restore
When it happens
Trigger: Reading a message sequence from the backup stream where hdr.HeaderSize exceeds the length of the buffer returned by io.ReadAll(tr); typically caused by a truncated/corrupted backup archive, bit rot, or a backup written by an incompatible encoder.
Common situations: Restoring a stream backup file that was truncated mid-transfer (partial rsync/S3 upload), editing or re-compressing a backup file, restoring across incompatible nats-server versions, or disk corruption on the archive.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to read message sequence %d: unexpected payload size
- message sequence %d out of order
- backup was truncated
- rebuildState for block %d failed: %w
- bad index file
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/087276bdfc6ae92e.
Report an issue: GitHub.