gastownhall/beads · error
failed to stat config.yaml: %w
Error message
failed to stat config.yaml: %w
What it means
SetYamlConfigInDir stats <beadsDir>/config.yaml before writing; when Stat fails for any reason other than not-exists (permission denied, path is a directory, I/O error), the raw error is wrapped as 'failed to stat config.yaml'. It distinguishes real I/O problems from the friendly not-found message.
Source
Thrown at internal/config/yaml_config.go:296
return setYamlConfigAtPath(configPath, key, value)
}
// SetYamlConfigInDir sets a configuration value in the config.yaml located in
// the provided beadsDir, bypassing CWD/worktree discovery. Use this when the
// caller has already resolved the authoritative workspace and needs to avoid
// local worktree stubs shadowing the real shared config location.
func SetYamlConfigInDir(beadsDir, key, value string) error {
// Validate specific keys (GH#995)
if err := validateYamlConfigValue(key, value); err != nil {
return err
}
configPath := filepath.Join(beadsDir, "config.yaml")
if _, err := os.Stat(configPath); err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("no config.yaml found in %s (run 'bd init' first)", beadsDir)
}
return fmt.Errorf("failed to stat config.yaml: %w", err)
}
return setYamlConfigAtPath(configPath, key, value)
}
var userGlobalKeyPrefixes = []string{"metrics."}
// userGlobalExactKeys are per-MACHINE settings that must never be written to
// the project .beads/config.yaml, which is a git-TRACKED file (see
// cmd/bd/doctor/gitignore.go: nothing in .beads/.gitignore excludes it). A
// committed value propagates one machine's answer to every clone that pulls
// it, which for these keys is worse than having no value at all.
//
// node_id is the exemplar: it names the beads STORE that grants leases here,
// and the reclaim guard (issueops.ReclaimExpiredLeasesInTx) compares it
// against each lease's granted_node. Commit "node_id: mini" and every replica
// reads "mini", so every comparison matches and the guard is simultaneously
// fully ARMED and fully INERT — laptop reaps mini's leases exactly as if theyView on GitHub (pinned to 71377f2769)
Solutions
- Check permissions on the .beads directory and fix ownership: ls -la <dir>/.beads; chown/chmod as needed.
- Inspect what config.yaml actually is (file vs directory): if it is a directory, remove or rename it and recreate the file.
- Verify the mount is writable and healthy (dmesg / remount rw) if on NFS/network storage.
- Read the wrapped %w cause in the message for the exact errno and address it directly.
Example fix
// before (config.yaml is a directory) rm -rf /proj/.beads/config.yaml // after rm -rf /proj/.beads/config.yaml bd init # recreates config.yaml as a regular file
Defensive patterns
Strategy: try-catch
Validate before calling
fi, err := os.Lstat(filepath.Join(beadsDir, "config.yaml"))
if err == nil && fi.IsDir() {
return fmt.Errorf("%s is a directory, expected a file", fi.Name())
}
if err := unix.Access(beadsDir, unix.W_OK); err != nil {
return fmt.Errorf(".beads dir not writable: %w", err)
} Try / catch
err := config.SetYamlConfigInDir(dir, key, value)
var pe *fs.PathError
if errors.As(err, &pe) {
return fmt.Errorf("filesystem problem at %s (%v): check permissions/mount", pe.Path, pe.Err)
} Prevention
- Keep config.yaml a regular file; never mkdir over it.
- Normalize ownership after sudo/root runs (chown -R $USER .beads).
- Avoid keeping .beads on flaky network mounts; use local disk.
- Check the wrapped cause (%w) for the exact errno before retrying.
When it happens
Trigger: os.Stat on the config.yaml path fails with a non-ENOENT error: the path exists but is a directory named config.yaml, the .beads directory is unreadable (permissions), or a filesystem/I/O error occurs (EIO, stale NFS mount).
Common situations: config.yaml accidentally replaced by a directory; .beads dir with restrictive ownership after sudo/copy; read-only or disconnected network mounts.
Related errors
- write metadata.json: %w
- failed to save config: %w
- failed to set beads.role config: %w
- failed to write config.yaml: %w
- failed to read config.yaml: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/bd499212693a3d42.
Report an issue: GitHub.