{"record":{"id":"bf9a2ebc169ff288","repo":"rqlite/rqlite","slug":"failed-to-get-last-modified-time-s","errorCode":null,"errorMessage":"failed to get last modified time: %s","messagePattern":"failed to get last modified time: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/store.go","lineNumber":2849,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get latest snapshot index post restore: %s\", err)\n\t}\n\n\t// Installed SQLite database is safe for fast restarts again. It is fingerprinted\n\t// against the very index and term the node is adopting here, so that a restart\n\t// can tell that the two still correspond to one another.\n\tif err := s.createSnapshotFingerprint(li, tm); err != nil {\n\t\treturn fmt.Errorf(\"failed to create snapshot fingerprint post restore: %s\", err)\n\t}\n\n\ts.fsmIdx.Store(li)\n\ts.fsmTarget.Signal(li)\n\ts.fsmTerm.Store(tm)\n\ts.dbAppliedIdx.Store(li)\n\ts.appliedTarget.Signal(li)\n\tlt, err := s.db.DBLastModified()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get last modified time: %s\", err)\n\t}\n\ts.dbModifiedTime.Store(lt)\n\t// Swapping in a new database deactivates the CDC hooks, so signal that it\n\t// needs to be reregistered on the next commit.\n\ts.cdcRegistered.Unset()\n\n\tstats.Add(numRestores, 1)\n\ts.logger.Printf(\"node restored in %s\", time.Since(startT))\n\treturn nil\n}\n\n// ForceSnapshotRestore forces the Store to restore its state from the Snapshot\n// Store on startup. Store must be closed before calling. Mostly useful for testing.\nfunc (s *Store) ForceSnapshotRestore() error {\n\tif s.open.Is() {\n\t\treturn ErrOpen\n\t}\n","sourceCodeStart":2831,"sourceCodeEnd":2867,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/store/store.go#L2831-L2867","documentation":"Wraps a failure from s.db.DBLastModified() at the tail of the restore. The node records the installed database's modification time so it can serve fast restarts and staleness checks; if SQLite cannot report the last-modified time of the newly installed DB, the restore fails at this final step.","triggerScenarios":"Right after swapping in the restored database, the query for the DB file's last-modified time fails — the installed file is missing/unreadable post-swap, the DB handle is in a bad state, or the underlying filesystem stat fails (network filesystem, I/O error).","commonSituations":"The swap step half-completed leaving no readable database file; NFS/network storage hiding the just-swapped file; filesystem I/O errors; race where external tooling moved the database file.","solutions":["Check that the expected SQLite file exists and is readable in the data directory (ls -l)","Retry the restore/boot once the filesystem is healthy","Avoid network filesystems for the data directory; use local disk","Check logs for the preceding 'error swapping database file' that may have left state inconsistent","Restart the node and let it rejoin/re-restore from the leader"],"exampleFix":"// before: DB file on flaky NFS mount\n$ df -T /var/rqlite/data  # nfs\n// after\n$ mv /var/rqlite/data /var/rqlite/data.local && ln -s local ... # or reconfigure datadir to local disk","handlingStrategy":"validation","validationCode":"# verify the DB file exists and is stat-able right after swap\n$ sudo -u rqlite stat /var/rqlite/data/db.sqlite","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use local disk instead of NFS/EFS for the data directory","Don't run external file movers on the live data dir","Check that db.Swap succeeded in logs before diagnosing downstream errors","Alert on filesystem I/O errors"],"tags":["sqlite","filesystem","restore","stat"],"backgroundTag":"db-stat-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"}