gastownhall/beads · error
failed to create backup dir in git-repo: %w
Error message
failed to create backup dir in git-repo: %w
What it means
backupDir determines the local backup directory. When backup.git-repo is configured and points at a valid git repo, it creates <gitRepo>/backup with 0700 permissions; if os.MkdirAll fails (permissions, read-only filesystem, path conflicts), it wraps the OS error as 'failed to create backup dir in git-repo: %w'. The wrapped cause names the exact filesystem problem.
Source
Thrown at cmd/bd/backup_export.go:40
}
// backupDir returns the backup directory path, creating it if needed.
// When backup.git-repo is set to a valid git repo, returns a backup/ subdirectory
// inside that repo. Otherwise it requires an active beads workspace and uses its
// backup/ subdirectory.
func backupDir() (string, error) {
gitRepo := config.GetString("backup.git-repo")
if gitRepo != "" {
if strings.HasPrefix(gitRepo, "~/") {
home, _ := os.UserHomeDir()
gitRepo = filepath.Join(home, gitRepo[2:])
}
if _, err := os.Stat(filepath.Join(gitRepo, ".git")); err != nil {
fmt.Fprintf(os.Stderr, "Warning: backup.git-repo %s is not a git repo, falling back to .beads/backup\n", gitRepo)
} else {
dir := filepath.Join(gitRepo, "backup")
if err := os.MkdirAll(dir, 0700); err != nil {
return "", fmt.Errorf("failed to create backup dir in git-repo: %w", err)
}
return dir, nil
}
}
beadsDir := beads.FindBeadsDir()
if beadsDir == "" {
return "", fmt.Errorf("%s; %s", activeWorkspaceNotFoundError(), diagHint())
}
dir := filepath.Join(beadsDir, "backup")
if err := os.MkdirAll(dir, 0700); err != nil {
return "", fmt.Errorf("failed to create backup directory: %w", err)
}
return dir, nil
}
// loadBackupState reads the backup state file, returning a zero state if missing.
func loadBackupState(dir string) (*backupState, error) {
path := filepath.Join(dir, "backup_state.json")View on GitHub (pinned to 71377f2769)
Solutions
- Check permissions on the git-repo parent directory and ensure the process user can create directories there
- Remove or rename any non-directory file at <gitRepo>/backup that blocks MkdirAll
- Unset backup.git-repo to fall back to .beads/backup inside the writable workspace
- Check the wrapped OS error (permission denied vs read-only) and fix the mount or ACL accordingly
Example fix
// before # backup.git-repo = /mnt/readonly/repo bd backup export // error: failed to create backup dir in git-repo: mkdir /mnt/readonly/repo/backup: read-only file system // after: point git-repo at a writable location or drop the setting bd config set backup.git-repo /home/user/repo # or unset it
Defensive patterns
Strategy: validation
Validate before calling
gitRepo := cfg.BackupGitRepo
if st, err := os.Stat(filepath.Join(gitRepo, ".git")); err == nil && st.IsDir() {
if f, err := os.OpenFile(gitRepo, os.O_WRONLY, 0700); err != nil {
return fmt.Errorf("git-repo %s not writable: %w", gitRepo, err)
} else { f.Close() }
} Try / catch
dir, err := backupDir()
if err != nil {
if strings.Contains(err.Error(), "failed to create backup dir in git-repo") {
// fall back to default .beads/backup or abort with a clear message
}
return err
} Prevention
- Point backup.git-repo at a writable, real git repository (contains .git)
- Pre-create and permission the <gitRepo>/backup directory in provisioning
- Watch for the stderr warning about invalid git-repo and fix config promptly
When it happens
Trigger: Running backup export (runBackupExport) or auto-backup (maybeAutoBackup) with backup.git-repo set, where creating <gitRepo>/backup fails: parent dir not writable, gitRepo path on a read-only mount, or a file named 'backup' already exists at that path.
Common situations: git-repo on a read-only CI volume, permission-restricted shared server, SELinux/AppArmor restrictions, or a stale regular file blocking the 'backup' directory path.
Related errors
- failed to create backup directory: %w
- failed to read backup state: %w
- failed to create backup file: %w
- failed to write issue %s: %w
- backup destination does not exist: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ddb2efc485d9a5ac.
Report an issue: GitHub.