{"record":{"id":"461adaca9d9f4053","repo":"rqlite/rqlite","slug":"error-swapping-database-file-v","errorCode":null,"errorMessage":"error swapping database file: %v","messagePattern":"error swapping database file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/store.go","lineNumber":2025,"sourceCode":"\t\treturn n, err\n\t}\n\n\t// Confirm the data is a valid SQLite database.\n\tif !sql.IsValidSQLiteFile(f.Name()) {\n\t\treturn n, fmt.Errorf(\"invalid SQLite data\")\n\t}\n\n\t// Raft won't snapshot unless there is at least one unsnapshotted log entry,\n\t// so prep that now before we do anything destructive.\n\tif af, err := s.Noop(\"boot\"); err != nil {\n\t\treturn n, err\n\t} else if err := af.Error(); err != nil {\n\t\treturn n, err\n\t}\n\n\t// Swap in new database file.\n\tif err := s.db.Swap(f.Name(), s.dbConf.FKConstraints, true); err != nil {\n\t\treturn n, fmt.Errorf(\"error swapping database file: %v\", err)\n\t}\n\n\t// Swapping in a new database unregisters any registered CDC hooks, so signal that it\n\t// needs to be reregistered on the next change.\n\ts.cdcRegistered.Unset()\n\n\t// Snapshot, so we load the new database into the Raft system.\n\tif err := s.snapshotStore.SetDueNext(snapshot.Full); err != nil {\n\t\ts.logger.Fatalf(\"failed to set full snapshot needed: %s\", err)\n\t}\n\tif err := s.Snapshot(1); err != nil {\n\t\treturn n, err\n\t}\n\tstats.Add(numBoots, 1)\n\treturn n, nil\n}\n\n// Vacuum performs a VACUUM operation on the underlying database.","sourceCodeStart":2007,"sourceCodeEnd":2043,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/store/store.go#L2007-L2043","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncurl -X POST http://node:4001/boot --data-binary @backup.db\n# after (FK-enabled node)\ncurl -X POST 'http://node:4001/boot?fk' --data-binary @backup.db","handlingStrategy":"retry","validationCode":"cmd := exec.Command(\"sqlite3\", \"backup.db\", \"PRAGMA integrity_check;\")\nif err := cmd.Run(); err != nil {\n    return errors.New(\"backup fails integrity check; do not boot from it\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := http.Post(bootURL, \"application/octet-stream\", body)\nif resp.StatusCode != 200 && strings.Contains(readBody(resp), \"error swapping database file\") {\n    checkDiskSpaceAndPerms(dataDir)\n    retryBoot(withMatchingFkFlag)\n}","preventionTips":["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"],"tags":["restore","sqlite","filesystem","boot"],"backgroundTag":"database-swap-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"}