gastownhall/beads · error
failed to inspect %s: %w
Error message
failed to inspect %s: %w
What it means
fixBeadsDirPermissions starts with os.Lstat on the beads directory; this error wraps any Lstat failure other than not-exist (which is treated as 'nothing to fix'). It means the path could not be inspected — typically a permission problem on a parent directory, a broken link situation Lstat itself reports, or an I/O error. The underlying error is preserved with %w.
Source
Thrown at internal/config/permissions.go:54
// FixBeadsDirPermissions sets the .beads directory to BeadsDirPerm when it
// has group or world-accessible bits. Returns true if permissions changed.
func FixBeadsDirPermissions(path string) (bool, error) {
return fixBeadsDirPermissions(path, openBeadsDirHandle)
}
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() }()
View on GitHub (pinned to 71377f2769)
Solutions
- Check permissions on each path component leading to the beads directory (need execute/search on parents).
- Resolve any symlink loops: `namei -l <path>` or inspect with ls -l; remove the cycle.
- Check whether the volume holding the path is mounted and healthy (dmesg / mount output).
- If running in a container or as another user, run with sufficient privileges or fix ownership of the parent directories.
Example fix
// before
fixBeadsDirPermissions("/home/otheruser/.beads", ...) // parent not searchable
// after
chmod o+x /home/otheruser # restore search permission on parent
# then retry FixBeadsDirPermissions Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check traversability before the fix call:
for d := filepath.Dir(path); ; d = filepath.Dir(d) {
if _, err := os.Stat(d); err != nil {
return fmt.Errorf("path component %s unreachable: %w", d, err)
}
if d == filepath.Dir(d) { break }
} Try / catch
fixed, err := config.FixBeadsDirPermissions(beadsDir)
if err != nil {
if strings.Contains(err.Error(), "failed to inspect") {
return fmt.Errorf("cannot access %s: %w — check parent dir permissions and symlinks", beadsDir, err)
}
return err
} Prevention
- Ensure parent directories grant the running user search (x) permission.
- Avoid symlink loops in beads dir paths; use canonical absolute paths (filepath.EvalSymlinks at setup).
- Verify volume mounts before running permission fixes on external storage.
- Run permission remediation as the same user that owns the beads directory.
When it happens
Trigger: os.Lstat on the beads dir path fails with an error that is not os.IsNotExist — e.g. EACCES on a parent directory, ELOOP from a symlink cycle, or EIO on the filesystem.
Common situations: A parent directory was chmod'd to remove search permission; a symlink loop in the path; a network/external volume went offline; running as a user without traverse rights (common in containers or multi-user machines).
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- dolt path is not executable
- failed to create backup directory: %w
- failed to create temp file: %w
- create beads directory: %w
- write metadata.json: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6bfb25fc1f21d51a.
Report an issue: GitHub.