gastownhall/beads · error
backup destination is not a directory: %s
Error message
backup destination is not a directory: %s
What it means
Returned by BackupDatabase when the destination path exists but is a regular file (or other non-directory), not a directory. Dolt file:// backup remotes must point at a directory, so the store rejects the argument with this plain (non-wrapped) message.
Source
Thrown at internal/storage/embeddeddolt/version_control.go:737
})
}
func (s *EmbeddedDoltStore) BackupRemove(ctx context.Context, name string) error {
return s.withMutatingDBConn(ctx, func(db versioncontrolops.DBConn) error {
return versioncontrolops.BackupRemove(ctx, db, name)
})
}
// BackupDatabase registers dir as a file:// Dolt backup remote and syncs
// the database to it. The dir must exist locally. This preserves full Dolt
// commit history.
func (s *EmbeddedDoltStore) 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"
return s.withMutatingDBConn(ctx, func(db versioncontrolops.DBConn) error {
// Register as a backup remote (idempotent — remove first if exists).
_ = versioncontrolops.BackupRemove(ctx, db, backupName)
if err := versioncontrolops.BackupAdd(ctx, db, backupName, backupURL); err != nil {
// Another backup (e.g. "default" registered by `bd backup init`) may
// already point to this URL. In that case, sync using the existing
// remote name rather than failing.
if conflict := versioncontrolops.ExtractAddressConflictName(err); conflict != "" {
if syncErr := versioncontrolops.BackupSync(ctx, db, conflict); syncErr != nil {
return fmt.Errorf("sync to backup: %w", syncErr)View on GitHub (pinned to 71377f2769)
Solutions
- Pass a directory path, not a file: mkdir the intended backup dir and re-run
- If a file exists at the path, remove/rename it and create a directory
- Verify with `ls -la <path>` that the target is a directory
- Use DirToFileURL-compatible absolute directory paths
Example fix
// before
store.BackupDatabase(ctx, "/backups/beads.tar.gz") // a file
// after
os.MkdirAll("/backups/beads", 0o755)
store.BackupDatabase(ctx, "/backups/beads") Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(dir)
if err != nil || !info.IsDir() {
return fmt.Errorf("%%s must be an existing directory", dir)
} Prevention
- Point backups at directories, never files or archives
- Verify targets with ls -la in setup scripts
- Avoid symlink chains that can resolve to files
When it happens
Trigger: Calling BackupDatabase(ctx, dir) where os.Stat(dir) succeeds but info.IsDir() is false — e.g. passing a tarball path, a config file, or the database file itself instead of a directory.
Common situations: Pointing backup at an archive file expecting it to 'restore into' it; passing the .bdb/db file instead of its parent directory; a symlink resolving to a file.
Related errors
- backup destination does not exist: %w
- dolt path is not executable
- no backup destination configured
- failed to remove backup: %w
- failed to create backup dir in git-repo: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/4d7034f028c80b6b.
Report an issue: GitHub.