gastownhall/beads · error

failed to chmod %s to %04o: %w

Error message

failed to chmod %s to %04o: %w

What it means

The chmod itself failed after all safety checks passed. The code holds a valid, verified directory handle and calls dir.Chmod(0700); this error wraps whatever the underlying fchmod returned, with the target mode (%04o) included in the message.

Source

Thrown at internal/config/permissions.go:81

	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)
	}
	if err := dir.Chmod(BeadsDirPerm); err != nil {
		return false, fmt.Errorf("failed to chmod %s to %04o: %w", path, BeadsDirPerm, err)
	}
	return true, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check ownership with ls -ld and run as the owner (or fix ownership with chown).
  2. Verify the filesystem is writable (mount | grep ro) and remount read-write if needed.
  3. Clear immutability flags: chattr -i <path> (Linux).
  4. If the filesystem does not support chmod (e.g. some network mounts), move .beads onto a local filesystem or accept the warning.

Example fix

// before: EPERM because directory owned by root
// after
$ sudo chown $(whoami) .beads
$ chmod 700 .beads
Defensive patterns

Strategy: try-catch

Validate before calling

info, err := os.Stat(beadsDir)
if err != nil {
    return err
}
if st, ok := info.Sys().(*syscall.Stat_t); ok && int(st.Uid) != os.Getuid() {
    return fmt.Errorf("%s not owned by current user; fchmod will fail", beadsDir)
}

Try / catch

changed, err := config.FixBeadsDirPermissions(beadsDir)
var pathErr *os.PathError
if err != nil && errors.As(err, &pathErr) && errors.Is(pathErr.Err, syscall.EPERM) {
    log.Printf("cannot chmod %s: run as owner or fix with sudo chown", beadsDir)
}

Prevention

When it happens

Trigger: Calling FixBeadsDirPermissions on a group/world-readable .beads directory when fchmod fails — typically EPERM (not the owner, or read-only filesystem), EROFS (read-only mount), or filesystem-level immutability/ACL restrictions.

Common situations: Running as a non-root user on a directory owned by another account; .beads on a read-only bind mount or container layer; immutable flag set (chattr +i); filesystems that ignore/reject chmod (some network mounts).

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/030cc307438eec1c. Report an issue: GitHub.