gastownhall/beads · error

backup destination does not exist: %w

Error message

backup destination does not exist: %w

What it means

BackupDatabase was asked to back the Dolt database up into `dir`, but os.Stat(dir) failed, meaning the destination path does not exist (or is otherwise inaccessible). The error wraps the underlying os.Stat error (e.g. 'no such file or directory', 'permission denied'). The backup is aborted before any remote registration or sync happens.

Source

Thrown at internal/storage/dolt/store.go:1294

	db, err := s.oneShotConn(0)
	if err != nil {
		return err
	}
	defer db.Close()
	return versioncontrolops.BackupSync(ctx, db, name)
}

// BackupRemove removes a configured Dolt backup destination.
func (s *DoltStore) BackupRemove(ctx context.Context, name string) error {
	return versioncontrolops.BackupRemove(ctx, s.db, name)
}

// BackupDatabase registers dir as a file:// Dolt backup remote and syncs
// the full database to it, preserving complete commit history.
func (s *DoltStore) BackupDatabase(ctx context.Context, dir string) error {
	info, err := os.Stat(dir)
	if err != nil {
		return fmt.Errorf("backup destination does not exist: %w", err)
	}
	if !info.IsDir() {
		return fmt.Errorf("backup destination is not a directory: %s", dir)
	}

	backupURL, err := versioncontrolops.DirToFileURL(dir)
	if err != nil {
		return err
	}
	backupName := "backup_export"

	syncDB, err := s.oneShotConn(0)
	if err != nil {
		return err
	}
	defer syncDB.Close()

	// Register as a backup remote (idempotent — remove first if exists).

View on GitHub (pinned to 71377f2769)

Solutions

  1. Create the destination directory first: mkdir -p <dir> (BackupDatabase requires an existing directory, it will not create one).
  2. Check the wrapped os.Stat error: 'no such file or directory' means create it; 'permission denied' means fix ownership/permissions or run as the right user.
  3. Verify you are passing an absolute path or running from the intended working directory if using a relative path.
  4. Confirm the volume/mount holding the destination is actually mounted.

Example fix

// before
err := store.BackupDatabase(ctx, "/backups/beads") // dir missing
// after
if err := os.MkdirAll("/backups/beads", 0o755); err != nil {
    return err
}
err := store.BackupDatabase(ctx, "/backups/beads")
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(dir)
if err != nil {
    if os.IsNotExist(err) {
        if err := os.MkdirAll(dir, 0o755); err != nil { return err }
    } else {
        return err
    }
}

Type guard

func isExistingDir(path string) bool {
    info, err := os.Stat(path)
    return err == nil && info.IsDir()
}

Try / catch

if err := store.BackupDatabase(ctx, dir); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && os.IsNotExist(pe) {
        os.MkdirAll(dir, 0o755)
        err = store.BackupDatabase(ctx, dir)
    }
}

Prevention

When it happens

Trigger: Calling DoltStore.BackupDatabase(ctx, dir) with a directory path that has not been created yet, a typo'd path, or a path the process cannot stat due to permissions — before BackupAdd/BackupSync ever run.

Common situations: Using `bd backup init`/`bd backup` with a relative path from the wrong working directory; pointing at a path on an unmounted volume; automation that assumes the tool creates the destination (it does not); running as a user lacking access to the path.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/a78b83e685c49661. Report an issue: GitHub.