rqlite/rqlite · error

failed to rename database: %s

Error message

failed to rename database: %s

What it means

Once old files are removed, Swap renames the new SQLite file into the canonical database path using os.Rename. A failure here (cross-device move, missing source, permission issue) aborts the swap with this error.

Source

Thrown at db/swappable_db.go:65

// Swap swaps the underlying database with that at the given path. The Swap operation
// may fail on some platforms if the file at path is open by another process. It is
// the caller's responsibility to ensure the file at path is not in use.
func (s *SwappableDB) Swap(path string, fkConstraints, walEnabled bool) error {
	if !IsValidSQLiteFile(path) {
		return fmt.Errorf("invalid SQLite data")
	}

	s.dbMu.Lock()
	defer s.dbMu.Unlock()
	if err := s.db.Close(); err != nil {
		return fmt.Errorf("failed to close: %s", err)
	}
	if err := RemoveFiles(s.db.Path()); err != nil {
		return fmt.Errorf("failed to remove files: %s", err)
	}
	if err := os.Rename(path, s.db.Path()); err != nil {
		return fmt.Errorf("failed to rename database: %s", err)
	}

	db, err := OpenWithDriver(s.drv, s.db.Path(), fkConstraints, walEnabled)
	if err != nil {
		return fmt.Errorf("open SQLite file failed: %s", err)
	}
	s.db = db
	if err := s.checkpointMgr.Close(); err != nil {
		return fmt.Errorf("failed to close checkpoint manager: %s", err)
	}
	mgr, err := NewCheckpointManager(db)
	if err != nil {
		return fmt.Errorf("failed to recreate checkpoint manager: %s", err)
	}
	s.checkpointMgr = mgr
	return nil
}

View on GitHub (pinned to 7586a4d1bd)

Solutions

  1. Write the restore temp file on the same filesystem as the database path
  2. Confirm the source file exists and hasn't been removed by a previous partial Swap
  3. Check write permission on the destination data directory
  4. Retry the restore with a fresh temp file

Example fix

// before
err := db.Swap("/tmp/restore.sqlite") // /tmp on tmpfs, data on /var
// after
f, _ := os.CreateTemp(dataDir, "restore-*") // same filesystem as DB
err := db.Swap(f.Name())
Defensive patterns

Strategy: validation

Validate before calling

func sameFS(a, b string) (bool, error) {
    ia, ib := syscall.Stat_t{}, syscall.Stat_t{}
    if err := syscall.Stat(filepath.Dir(a), &ia); err != nil { return false, err }
    if err := syscall.Stat(filepath.Dir(b), &ib); err != nil { return false, err }
    return ia.Dev == ib.Dev, nil
}

Try / catch

if err := db.Swap(path); err != nil {
    if strings.Contains(err.Error(), "failed to rename database") {
        return fmt.Errorf("ensure %s exists and shares a filesystem with the data dir", path)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Swap when the source temp file `path` no longer exists, or source and destination live on different filesystems (EXDEV), or the destination directory is not writable.

Common situations: Staging restore files on /tmp (tmpfs) while the data dir is on another mount; temp file already consumed by a prior failed Swap; insufficient directory permissions.

Related errors


AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03). Data as JSON: /api/errors/ce9f79679fa533f9. Report an issue: GitHub.