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

  1. Re-create the backup and transfer it again, verifying byte size/checksum end-to-end
  2. Ensure the backup process completed successfully before attempting restore
  3. Check for connection drops between backup and restore (proxies, timeouts) and increase limits
  4. 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

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


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