canopy-network/canopy · error

rotate backup

Error message

rotate backup: %w

What it means

Wrapped failure (fmt.Errorf with %w) around os.Rename when rotating the previous backup directory out of the way (backupDir -> prevBackupDir) during backup finalization. On Unix this is atomic; failures indicate path problems, permissions, or cross-device rename issues in the backup rotation scheme.

Solutions

  1. Verify backupDir and prevBackupDir are on the same filesystem (os.Rename fails across devices).
  2. Remove stale prevBackupDir if a prior crashed rotation left it in a conflicting state.
  3. Check parent-directory write permissions needed for the rename.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at store/store.go:795 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06). Data as JSON: /api/errors/7c28673b0327a5f4. Report an issue: GitHub.

Appendix: source

Thrown at store/store.go:795

			s.mu.Unlock()
			err = fmt.Errorf("flush before checkpoint: %w", err)
			return
		}
		s.mu.Unlock()
		// perform the backup using pebble's checkpointing mechanism which creates a
		// consistent snapshot of the database at the specified directory
		if err = s.db.Checkpoint(tempBackupDir); err != nil {
			err = fmt.Errorf("checkpoint creation: %w", err)
			return
		}
		// write the current height to a separate file
		heightFile := filepath.Join(tempBackupDir, "height.txt")
		if err = os.WriteFile(heightFile, fmt.Appendf(nil, "%d", version), 0644); err != nil {
			err = fmt.Errorf("write height file: %w", err)
			return
		}
		if err = os.Rename(backupDir, prevBackupDir); err != nil && !os.IsNotExist(err) {
			err = fmt.Errorf("rotate backup: %w", err)
			return
		}
		// promote: atomically move the temp backup into the active slot
		if err = os.Rename(tempBackupDir, backupDir); err != nil {
			err = fmt.Errorf("finalize backup: %w", err)
			return
		}
		backupDuration := time.Since(start)
		// log results
		s.log.Infof("backup completed at height [%d] in %s", version, backupDuration)
		// update metrics
		s.metrics.UpdateStoreJobMetrics(0, 0, backupDuration)
	}()
}

// Compact runs Pebble range compaction over the prefix range
func (s *Store) Compact(version uint64, prefix []byte) lib.ErrorI {
	// compactions are not allowed to run concurrently to not intertwine with the keys

View on GitHub (pinned to ee8197d91d)