nats-io/nats-server · error
backup was truncated
Error message
backup was truncated
What it means
RestoreStreamV2 reads message blocks until an end-of-backup (EOB) marker is received. If the reader signals completion without the EOB marker, the backup is incomplete and the server refuses the restore with 'backup was truncated', rather than restoring a partial stream silently.
Source
Thrown at server/stream_backup.go:547
}
hdrTime := time.Unix(0, hdr.Timestamp)
if ttl > 0 && time.Now().After(hdrTime.Add(time.Duration(ttl)*time.Second)) {
// If the TTL has exceeded then there isn't much point in storing the message,
// but we still need to preserve the sequence.
if err := store.SkipMsgs(seq, 1); err != nil {
return nil, fmt.Errorf("failed to process expired message sequence %d: %w", seq, err)
}
releaseRestoreBytes(storedSize)
continue
}
if err = store.StoreRawMsg(subj, mhdr, msg, seq, hdr.Timestamp, ttl, false); err != nil {
return nil, fmt.Errorf("failed to store message sequence %d: %w", seq, err)
}
releaseRestoreBytes(storedSize)
}
if !eob {
return mset, fmt.Errorf("backup was truncated")
}
// Need to make sure that we pad out with skip msgs to preserve the last
// sequence, otherwise trailing deleted messages could reuse sequence numbers.
if lseq < nstate.LastSeq {
gap := nstate.LastSeq - lseq
if err := store.SkipMsgs(lseq+1, gap); err != nil {
return nil, fmt.Errorf("failed to process trailing gap: %w", err)
}
}
return mset, nil
}
View on GitHub (pinned to 3a66a489d2)
Solutions
- Re-create the backup and transfer it again, verifying byte size/checksum end-to-end
- Ensure the backup process completed successfully before attempting restore
- Check for connection drops between backup and restore (proxies, timeouts) and increase limits
- Never restore from a file still being written or streamed; snapshot to a complete file first
Defensive patterns
Strategy: validation
Validate before calling
info, _ := os.Stat(path)
if !backupCompletedMarkerExists(path) || info.Size() < minExpectedSize { return fmt.Errorf("backup incomplete; refusing restore") } Try / catch
if err != nil && strings.Contains(err.Error(), "backup was truncated") {
// abort restore; re-transfer or re-create the backup before retrying
} Prevention
- Only restore from backups whose producing process completed successfully
- Verify checksums and sizes after every transfer
- Avoid streaming restores over unstable connections
- Snapshot to a complete file before restoring; never read files still being written
When it happens
Trigger: The restore reader ends (EOF) before the EOB block arrives; caused by a truncated backup file, an aborted backup process, dropped connection during a streamed restore, or reading a file still being written.
Common situations: Partial file uploads (S3/rsync interrupted), backing up a stream while the backup connection was cut, or piping the backup through a command that dropped the tail of the data.
Related errors
- failed to parse message sequence %d: invalid header length
- failed to read message sequence %d: unexpected payload size
- snapshot check failed: %w
- message sequence %d out of order
- failed to process gap: %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/af510cf0fb24bb5c.
Report an issue: GitHub.