{"record":{"id":"af510cf0fb24bb5c","repo":"nats-io/nats-server","slug":"backup-was-truncated","errorCode":null,"errorMessage":"backup was truncated","messagePattern":"backup was truncated","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream_backup.go","lineNumber":547,"sourceCode":"\t\t}\n\t\thdrTime := time.Unix(0, hdr.Timestamp)\n\t\tif ttl > 0 && time.Now().After(hdrTime.Add(time.Duration(ttl)*time.Second)) {\n\t\t\t// If the TTL has exceeded then there isn't much point in storing the message,\n\t\t\t// but we still need to preserve the sequence.\n\t\t\tif err := store.SkipMsgs(seq, 1); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to process expired message sequence %d: %w\", seq, err)\n\t\t\t}\n\t\t\treleaseRestoreBytes(storedSize)\n\t\t\tcontinue\n\t\t}\n\t\tif err = store.StoreRawMsg(subj, mhdr, msg, seq, hdr.Timestamp, ttl, false); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to store message sequence %d: %w\", seq, err)\n\t\t}\n\t\treleaseRestoreBytes(storedSize)\n\t}\n\n\tif !eob {\n\t\treturn mset, fmt.Errorf(\"backup was truncated\")\n\t}\n\n\t// Need to make sure that we pad out with skip msgs to preserve the last\n\t// sequence, otherwise trailing deleted messages could reuse sequence numbers.\n\tif lseq < nstate.LastSeq {\n\t\tgap := nstate.LastSeq - lseq\n\t\tif err := store.SkipMsgs(lseq+1, gap); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to process trailing gap: %w\", err)\n\t\t}\n\t}\n\treturn mset, nil\n}\n","sourceCodeStart":529,"sourceCodeEnd":560,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream_backup.go#L529-L560","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"info, _ := os.Stat(path)\nif !backupCompletedMarkerExists(path) || info.Size() < minExpectedSize { return fmt.Errorf(\"backup incomplete; refusing restore\") }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"backup was truncated\") {\n    // abort restore; re-transfer or re-create the backup before retrying\n}","preventionTips":["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"],"tags":["jetstream","restore","truncation","backup"],"backgroundTag":"truncated-backup-file","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}