gastownhall/beads · critical
restore from backup %s: %w
Error message
restore from backup %s: %w
What it means
BackupRestore's forced branch runs `CALL DOLT_BACKUP('restore', '--force', ?, ?)` to overwrite an existing database from a backup, wrapping failures as "restore from backup <url>: <cause>". It throws when the forced restore fails — bad URL, unreadable backup, or driver error. Because force overwrites data, failures here deserve careful inspection of the cause.
Source
Thrown at internal/storage/versioncontrolops/backup.go:40
}
return nil
}
// BackupRemove removes a configured Dolt backup destination.
func BackupRemove(ctx context.Context, db DBConn, name string) error {
if _, err := db.ExecContext(ctx, "CALL DOLT_BACKUP('rm', ?)", name); err != nil {
return fmt.Errorf("remove backup %s: %w", name, err)
}
return nil
}
// BackupRestore restores a database from a backup at the given URL into
// the named database. When force is true, an existing database with the
// same name is overwritten. Mirrors the CLI: dolt backup restore [--force] <url> <db_name>
func BackupRestore(ctx context.Context, db DBConn, url, dbName string, force bool) error {
if force {
if _, err := db.ExecContext(ctx, "CALL DOLT_BACKUP('restore', '--force', ?, ?)", url, dbName); err != nil {
return fmt.Errorf("restore from backup %s: %w", url, err)
}
} else {
if _, err := db.ExecContext(ctx, "CALL DOLT_BACKUP('restore', ?, ?)", url, dbName); err != nil {
return fmt.Errorf("restore from backup %s: %w", url, err)
}
}
return nil
}
// DirToFileURL resolves dir to an absolute path and returns a file:// URL.
func DirToFileURL(dir string) (string, error) {
abs, err := filepath.Abs(dir)
if err != nil {
return "", fmt.Errorf("resolve absolute path: %w", err)
}
return "file://" + abs, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Verify the backup URL exists and is readable before restoring (os.Stat for file:// paths)
- Resolve local dirs through DirToFileURL to get a correct file:// URL
- Ensure no clients hold the target database open during forced restore
- Inspect the wrapped cause for the exact Dolt rejection
Example fix
// before
vcops.BackupRestore(ctx, db, "/backups/db", "mydb", true)
// after
u, err := vcops.DirToFileURL("/backups/db")
if err != nil { return err }
if err := vcops.BackupRestore(ctx, db, u, "mydb", true); err != nil {
return fmt.Errorf("forced restore: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func backupExists(u string) error {
path := strings.TrimPrefix(u, "file://")
if path != u {
if _, err := os.Stat(path); err != nil { return fmt.Errorf("backup missing: %w", err) }
}
return nil
}
// call before BackupRestore(..., force=true) Try / catch
if err := vcops.BackupRestore(ctx, db, url, dbName, true); err != nil {
return fmt.Errorf("forced restore of %s failed; target db state unknown: %w", dbName, err)
} Prevention
- Snapshot/verify the target database before any forced restore
- Resolve paths with DirToFileURL and os.Stat the backup first
- Quiesce writers to the target database during restore
When it happens
Trigger: BackupRestore(ctx, db, url, dbName, true) when db.ExecContext fails: backup URL does not exist or is unreadable, dbName collides with a live database the server refuses to clobber, or connection error.
Common situations: Pointing at a file:// URL whose directory was moved or deleted; restoring over a database with open connections; URL built without DirToFileURL producing an invalid scheme.
Related errors
- no backup destination configured
- failed to remove backup: %w
- failed to get current commit: %w
- storage backend does not support backup operations
- failed to get current commit for state: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/785fde311974bfaa.
Report an issue: GitHub.