gastownhall/beads · error
refusing to chmod %s: path is not a directory
Error message
refusing to chmod %s: path is not a directory
What it means
fixBeadsDirPermissions refuses to chmod the path because os.Lstat shows it is not a directory (e.g. a regular file named .beads). chmod-ing a non-directory to 0700 would be meaningless for the intended directory-permission repair, so the call fails instead.
Source
Thrown at internal/config/permissions.go:60
type beadsDirHandle interface {
Stat() (os.FileInfo, error)
Chmod(os.FileMode) error
Close() error
}
func fixBeadsDirPermissions(path string, openDir func(string) (beadsDirHandle, error)) (bool, error) {
info, err := os.Lstat(path)
if err != nil {
if os.IsNotExist(err) {
return false, nil // directory doesn't exist yet
}
return false, fmt.Errorf("failed to inspect %s: %w", path, err)
}
if info.Mode()&os.ModeSymlink != 0 {
return false, fmt.Errorf("refusing to chmod %s: path is a symbolic link", path)
}
if !info.IsDir() {
return false, fmt.Errorf("refusing to chmod %s: path is not a directory", path)
}
perm := info.Mode().Perm()
if perm&0077 == 0 {
return false, nil // no group or world-accessible bits
}
dir, err := openDir(path)
if err != nil {
return false, fmt.Errorf("failed to open %s securely: %w", path, err)
}
defer func() { _ = dir.Close() }()
openedInfo, err := dir.Stat()
if err != nil {
return false, fmt.Errorf("failed to inspect opened directory %s: %w", path, err)
}
if !openedInfo.IsDir() || !os.SameFile(info, openedInfo) {
return false, fmt.Errorf("refusing to chmod %s: path changed during permission repair", path)View on GitHub (pinned to 71377f2769)
Solutions
- Check what is at the path with ls -la .beads.
- Remove or rename the non-directory entry (e.g. mv .beads .beads.bak).
- Recreate the directory with mkdir -m 700 .beads and re-run the operation.
- If the file contains data, inspect it before deleting — it may be a mislocated database file.
Example fix
// before: .beads is a regular file // after $ mv .beads .beads.file.bak $ mkdir -m 700 .beads
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(beadsDir)
if err == nil && !info.IsDir() {
return fmt.Errorf("%s exists but is not a directory; move it aside and run bd init", beadsDir)
} Type guard
func isDirectory(path string) bool {
info, err := os.Stat(path)
return err == nil && info.IsDir()
} Prevention
- Avoid shell redirections that could create a file named .beads.
- After failed init/restore operations, verify the path type before retrying.
- Use `bd init` to create the directory rather than manual mkdir with odd names.
When it happens
Trigger: Calling FixBeadsDirPermissions(path) where path exists but info.IsDir() is false — typically a regular file, fifo, or device node occupying the .beads path.
Common situations: A stray file named .beads was created accidentally (e.g. output redirection like `> .beads`); a failed init left a file where the directory should be; a sync tool replaced the directory with a file.
Related errors
- failed to create user config directory: %w
- uow: creating server root directory: %w
- dolt path is not executable
- failed to create backup directory: %w
- failed to create temp file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/47c0d3546b88b79b.
Report an issue: GitHub.