{"record":{"id":"9df13db2db69dec6","repo":"rqlite/rqlite","slug":"pre-backup-snapshot-failed-s","errorCode":null,"errorMessage":"pre-backup snapshot failed: %s","messagePattern":"pre-backup snapshot failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/store.go","lineNumber":1817,"sourceCode":"\t\t\tdefer os.Remove(srcFD.Name())\n\t\t\tdefer srcFD.Close()\n\t\t\tif err := s.db.Backup(srcFD.Name(), br.Vacuum); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\t// If there is data in the WAL we need to do a snapshot to ensure that the\n\t\t\t// backup we take of the main database file is up-to-date. Doing this check\n\t\t\t// is an optimization, it's not crticial that it is 100% correct as we still\n\t\t\t// check for the \"nothing new to snapshot\" error anyway.\n\t\t\tsz, err := s.db.WALSize()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif sz > 0 {\n\t\t\t\tif err := s.Snapshot(0); err != nil {\n\t\t\t\t\tif !errors.Is(err, ErrNothingNewToSnapshot) &&\n\t\t\t\t\t\t!strings.Contains(err.Error(), \"wait until the configuration entry at\") {\n\t\t\t\t\t\treturn fmt.Errorf(\"pre-backup snapshot failed: %s\", err.Error())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Block any snapshotting which will allow us to read the SQLite file without\n\t\t\t// it changing underneath us. Any incoming writes will be sent to the WAL, so\n\t\t\t// write traffic is not blocked during the backup process.\n\t\t\tif err := s.snapshotCAS.BeginWithRetry(\"backup\", backupCASTimeout, backupCASRetryDelay); err != nil {\n\t\t\t\treturn ErrBackupCASFailed\n\t\t\t}\n\t\t\tdefer s.snapshotCAS.End()\n\n\t\t\t// Now we can copy the SQLite file directly.\n\t\t\tsrcFD, err = os.Open(s.dbPath)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to open database file: %s\", err.Error())\n\t\t\t}\n\t\t\tdefer srcFD.Close()\n\t\t}","sourceCodeStart":1799,"sourceCodeEnd":1835,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/store/store.go#L1799-L1835","documentation":"During a backup operation, the Store takes a pre-backup snapshot (via s.Snapshot(0)) to ensure the Raft log is truncated and the SQLite file is in a stable state before it is copied. If the snapshot fails with an error that is not ErrNothingNewToSnapshot or the known 'wait until the configuration entry at...' condition, the backup aborts with 'pre-backup snapshot failed: %s'.","triggerScenarios":"Calling the /db/backup endpoint (Store.Backup) when the underlying raft.Snapshot() call fails for reasons other than 'nothing new to snapshot': Raft in a bad state, loss of leadership mid-operation, snapshot in progress, or I/O errors writing the snapshot.","commonSituations":"Automated backup cron jobs hitting /db/backup while the node is not leader or is mid-snapshot; disk full preventing snapshot writes; cluster instability during backup windows; large backlogs of unsnapshotted entries combined with I/O issues.","solutions":["Retry the backup after the transient Raft condition clears (election/snapshot completes).","Verify the node is the leader and Raft is healthy before triggering backups.","Check disk space and permissions on the snapshot directory.","If the cause is raft log compaction contention, increase -raft-snap thresholds or schedule backups off-peak."],"exampleFix":"// before\nstatus := 500; msg = fmt.Sprintf(\"pre-backup snapshot failed: %s\", err)\n// after (caller-side)\nif strings.Contains(err, \"pre-backup snapshot failed\") {\n    time.Sleep(2 * time.Second)\n    retryBackup()\n}","handlingStrategy":"retry","validationCode":"st := getNodeStatus(nodeURL)\nif st[\"store\"][\"raft\"][\"state\"] != \"leader\" || !st[\"store\"][\"raft\"][\"applied_index\"]... {\n    // trigger backup only on healthy leader\n}","typeGuard":"func isPreBackupSnapshotErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"pre-backup snapshot failed\")\n}","tryCatchPattern":"err := runBackup(nodeURL)\nif isPreBackupSnapshotErr(err) {\n    time.Sleep(5 * time.Second)\n    err = runBackup(nodeURL) // one retry after Raft settles\n}","preventionTips":["Trigger backups only against a healthy leader","Ensure adequate disk space for snapshots","Avoid overlapping backups and snapshot-heavy workloads","Schedule backups off-peak to reduce Raft contention"],"tags":["backup","raft","snapshot","io"],"backgroundTag":"pre-backup-snapshot-failed","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}