gastownhall/beads · error
failed to stat user config.yaml: %w
Error message
failed to stat user config.yaml: %w
What it means
SetUserYamlConfig stats the user config.yaml to decide whether to create it or update it. When Stat fails with an error other than not-exist (permission denied on the parent, path is a directory, I/O error), the error is wrapped as 'failed to stat user config.yaml'.
Source
Thrown at internal/config/yaml_config.go:502
}
func SetUserYamlConfig(key, value string) error {
if err := validateYamlConfigValue(key, value); err != nil {
return err
}
configPath, err := UserConfigYamlPath()
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(configPath), 0o755); err != nil {
return fmt.Errorf("failed to create user config directory: %w", err)
}
if _, err := os.Stat(configPath); os.IsNotExist(err) {
if err := os.WriteFile(configPath, []byte{}, 0o600); err != nil {
return fmt.Errorf("failed to create user config.yaml: %w", err)
}
} else if err != nil {
return fmt.Errorf("failed to stat user config.yaml: %w", err)
}
return setYamlConfigAtPath(configPath, key, value)
}
func setYamlConfigAtPath(configPath, key, value string) error {
// Normalize key to canonical yaml format
normalizedKey := normalizeYamlKey(key)
// Read existing config
content, err := os.ReadFile(configPath) //nolint:gosec // configPath is from findProjectConfigYaml
if err != nil {
return fmt.Errorf("failed to read config.yaml: %w", err)
}
// Update or add the key
newContent, err := updateYamlKey(string(content), normalizedKey, value)
if err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Check what config.yaml is: if it is a directory, rename/remove it and let bd recreate the file.
- Fix permissions on ~/.beads so the current user can traverse it (chmod u+rx ~/.beads, chown $USER).
- Address the underlying OS error from the wrapped %w cause (EACCES, ENOTDIR, EIO).
- If on a failing mount, move the home to healthy local storage by pointing HOME at a local writable dir.
Example fix
// before $ file ~/.beads/config.yaml .beads/config.yaml: directory bd config set ... // stat fails ENOTDIR // after rm -rf ~/.beads/config.yaml bd config set metrics.enabled true # recreated as file
Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Lstat(userConfigPath)
if err == nil && fi.IsDir() {
return fmt.Errorf("%s is a directory; remove it so bd can recreate config.yaml", userConfigPath)
}
if err := unix.Access(filepath.Dir(userConfigPath), unix.W_OK); err != nil {
return fmt.Errorf("cannot access %s: %w", filepath.Dir(userConfigPath), err)
} Try / catch
err := config.SetUserYamlConfig(key, value)
var pe *fs.PathError
if errors.As(err, &pe) && strings.Contains(err.Error(), "failed to stat user config.yaml") {
if fi, serr := os.Lstat(pe.Path); serr == nil && fi.IsDir() {
if rmErr := os.RemoveAll(pe.Path); rmErr != nil { return rmErr }
return config.SetUserYamlConfig(key, value)
}
return fmt.Errorf("fix permissions on %s: %w", filepath.Dir(pe.Path), pe)
} Prevention
- Keep config.yaml a regular file; investigate anything odd with `file`/`ls -la`.
- Avoid switching users (sudo) for bd config operations on the same home.
- Keep ~/.beads on healthy local storage, not failing FUSE/NFS mounts.
- Check the wrapped errno (EACCES/ENOTDIR/EIO) to pick the right fix.
When it happens
Trigger: os.Stat(configPath) returns a non-IsNotExist error during SetUserYamlConfig: ~/.beads/config.yaml exists as a directory, parent directory lacks execute/search permission, or a filesystem I/O error occurs.
Common situations: Broken ~/.beads layout (config.yaml is a dir); permission drift after running bd under different users (sudo/root); failing disk or FUSE mount.
Related errors
- write metadata.json: %w
- failed to save config: %w
- failed to set beads.role config: %w
- failed to write config.yaml: %w
- checking source sidecar %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7998eb9b7b875032.
Report an issue: GitHub.