benbjohnson/litestream · error

cannot remove tmp files: %w

Error message

cannot remove tmp files: %w

What it means

DB.Open calls removeTmpFiles(db.metaPath) to clean temporary files left over from a previous crash, and wraps any failure from that helper with this error. Tmp files are transient artifacts during replication/checkpointing; failure to remove them usually indicates a filesystem-level problem in the database's metadata directory.

Source

Thrown at db.go:793

	}
	// Recreate context for fresh start (handles reopen after close)
	db.ctx, db.cancel = context.WithCancel(context.Background())
	db.mu.Unlock()

	// Validate fields on database.
	if db.Replica == nil {
		return fmt.Errorf("replica required before opening database")
	}
	if db.Replica.Client == nil {
		return fmt.Errorf("replica client required before opening database")
	}
	if db.MinCheckpointPageN <= 0 {
		return fmt.Errorf("minimum checkpoint page count required")
	}

	// Clear old temporary files that my have been left from a crash.
	if err := removeTmpFiles(db.metaPath); err != nil {
		return fmt.Errorf("cannot remove tmp files: %w", err)
	}

	// Set the compactor client once before starting any goroutines.
	db.compactor.VerifyCompaction = db.VerifyCompaction
	db.compactor.RetentionEnabled = db.RetentionEnabled
	db.compactor.client = db.Replica.Client

	// Start monitoring SQLite database in a separate goroutine.
	if db.MonitorInterval > 0 {
		db.wg.Add(1)
		go func() { defer db.wg.Done(); db.monitor() }()
	}

	// Mark as opened only after successful initialization.
	db.mu.Lock()
	db.opened = true
	db.mu.Unlock()

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check filesystem permissions and free space on the volume holding the database and its metadata directory.
  2. Run as the user that owns the database files (or fix ownership with chown).
  3. Inspect the wrapped inner error (%w) to identify whether it is a directory-read or file-remove failure, and address that path.
Defensive patterns

Strategy: try-catch

Validate before calling

// check filesystem is writable before opening
if err := os.WriteFile(filepath.Join(filepath.Dir(dbPath), ".probe"), nil, 0o600); err != nil {
    return fmt.Errorf("data dir not writable: %w", err)
}

Try / catch

if err := db.Open(); err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) {
        log.Printf("filesystem problem at %s: %v", perr.Path, perr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: removeTmpFiles returns an error while scanning/removing files under the directory of db.metaPath — e.g. an OS-level read error or unexpected failure enumerating the directory.

Common situations: Read-only or full filesystem containing the database and its .litestream metadata; permission changes after restoring a volume; NFS/EFS hiccups during directory enumeration.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/464ea16bc49c561a. Report an issue: GitHub.