gastownhall/beads · error
failed to create backup directory: %w
Error message
failed to create backup directory: %w
What it means
After resolving the workspace, backupDir creates <beadsDir>/backup with 0700 permissions; if os.MkdirAll fails it wraps the OS error as 'failed to create backup directory: %w'. The underlying cause (permission denied, read-only filesystem, file blocking the path) is preserved for diagnosis.
Source
Thrown at cmd/bd/backup_export.go:51
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")
data, err := os.ReadFile(path) //nolint:gosec // path is constructed internally
if os.IsNotExist(err) {
return &backupState{}, nil
}
if err != nil {
return nil, fmt.Errorf("failed to read backup state: %w", err)
}
var state backupState
if err := json.Unmarshal(data, &state); err != nil {
return nil, fmt.Errorf("failed to parse backup state: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Fix ownership/permissions: chown/chmod the .beads directory so the running user can write (mkdir 0700 needs write+execute on .beads)
- Remove/rename any non-directory file at .beads/backup blocking creation
- Check the wrapped OS error for read-only or no-space conditions and free/repair accordingly
- Temporarily configure backup.git-repo to a writable alternate location
Example fix
// before bd backup export // error: failed to create backup directory: mkdir .beads/backup: permission denied // after sudo chown -R "$USER" .beads && bd backup export
Defensive patterns
Strategy: validation
Validate before calling
beadsDir := beads.FindBeadsDir()
if info, err := os.Stat(beadsDir); err != nil || !info.IsDir() || !writable(beadsDir) {
return fmt.Errorf(".beads dir missing or not writable: %s", beadsDir)
} Try / catch
dir, err := backupDir()
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
return fmt.Errorf("fix .beads permissions (chown/chmod) then retry: %w", err)
}
return err
} Prevention
- Do not create .beads as root if a normal user will run bd
- Ensure .beads lives on a writable volume; avoid read-only mounts
- Check for files named 'backup' colliding with the directory inside .beads
- Keep free disk space on the workspace volume
When it happens
Trigger: Running backup export / auto-backup inside a valid workspace whose .beads directory cannot host a 'backup' subdir: read-only .beads, ownership mismatch (e.g. created by another user/sudo), or a stale file named 'backup' inside .beads.
Common situations: Workspace cloned by root but operated by a normal user, .beads on a read-only mount or synced/locked by another tool, disk-full conditions, or antivirus/backup software holding locks on Windows mounts.
Related errors
- failed to create backup file: %w
- dolt path is not executable
- failed to create backup dir in git-repo: %w
- failed to read backup state: %w
- failed to create temp file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/602028d400fcaee8.
Report an issue: GitHub.