rqlite/rqlite · error
error swapping database file: %v
Error message
error swapping database file: %v
What it means
After a successful boot/restore, the Store swaps the freshly validated SQLite file into place via db.Swap(), which closes the current database handle and reopens the new file (reapplying FK constraints settings and WAL mode). If the swap fails (SQLite open error on the new file, missing WAL/journal handling problems, FK constraint flags mismatch, file I/O error), the restore fails with 'error swapping database file: %v'.
Source
Thrown at store/store.go:2025
return n, err
}
// Confirm the data is a valid SQLite database.
if !sql.IsValidSQLiteFile(f.Name()) {
return n, fmt.Errorf("invalid SQLite data")
}
// Raft won't snapshot unless there is at least one unsnapshotted log entry,
// so prep that now before we do anything destructive.
if af, err := s.Noop("boot"); err != nil {
return n, err
} else if err := af.Error(); err != nil {
return n, err
}
// Swap in new database file.
if err := s.db.Swap(f.Name(), s.dbConf.FKConstraints, true); err != nil {
return n, fmt.Errorf("error swapping database file: %v", err)
}
// Swapping in a new database unregisters any registered CDC hooks, so signal that it
// needs to be reregistered on the next change.
s.cdcRegistered.Unset()
// Snapshot, so we load the new database into the Raft system.
if err := s.snapshotStore.SetDueNext(snapshot.Full); err != nil {
s.logger.Fatalf("failed to set full snapshot needed: %s", err)
}
if err := s.Snapshot(1); err != nil {
return n, err
}
stats.Add(numBoots, 1)
return n, nil
}
// Vacuum performs a VACUUM operation on the underlying database.View on GitHub (pinned to 7586a4d1bd)
Solutions
- Check rqlited logs for the underlying SQLite open error and the data directory's permissions/free space.
- Retry the boot with the correct ?fk flag on /boot so FKConstraints matches the node configuration.
- Re-export/re-download the backup and verify it opens with the sqlite3 CLI locally.
- Stop write traffic, restart the node, and boot again to rule out transient races.
Example fix
# before curl -X POST http://node:4001/boot --data-binary @backup.db # after (FK-enabled node) curl -X POST 'http://node:4001/boot?fk' --data-binary @backup.db
Defensive patterns
Strategy: retry
Validate before calling
cmd := exec.Command("sqlite3", "backup.db", "PRAGMA integrity_check;")
if err := cmd.Run(); err != nil {
return errors.New("backup fails integrity check; do not boot from it")
} Try / catch
resp, err := http.Post(bootURL, "application/octet-stream", body)
if resp.StatusCode != 200 && strings.Contains(readBody(resp), "error swapping database file") {
checkDiskSpaceAndPerms(dataDir)
retryBoot(withMatchingFkFlag)
} Prevention
- Match the ?fk boot parameter to the node's FKConstraints setting
- Ensure free disk space and write permissions in the data directory
- Validate the restore file with sqlite3 PRAGMA integrity_check locally
- Quiesce writes and retry boot if a transient race is suspected
When it happens
Trigger: Calling /boot when the restored file cannot be opened/reopened by SQLite — e.g., file corrupted in a way IsValidSQLiteFile's header check passes but full open fails, filesystem permission problems on the data directory, or incompatible dbConf.FKConstraints state.
Common situations: Disk-full or permission errors on the data directory during swap; restoring a database created with different SQLite compile options or encryption; FKConstraints mismatch between the boot source and node configuration; concurrent operations racing the swap.
Related errors
- failed to remove files: %s
- failed to rename database: %s
- failed to get last modified time: %s
- ErrWALReplayDirectoryMismatch
- ErrWALAlreadyExists
AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03).
Data as JSON: /api/errors/461adaca9d9f4053.
Report an issue: GitHub.