gastownhall/beads · error
failed to read config.yaml: %w
Error message
failed to read config.yaml: %w
What it means
GetReposFromYAML reads config.yaml and wraps any read error other than NotExist (which is tolerated as an empty config) in this error. It indicates the config file exists but could not be read by the process.
Source
Thrown at internal/config/repos.go:41
// FindConfigYAMLPath finds the config.yaml file in .beads directory
// Walks up from CWD to find .beads/config.yaml
func FindConfigYAMLPath() (string, error) {
configPath, err := findProjectConfigYaml()
if err != nil {
return "", fmt.Errorf("no .beads/config.yaml found in current directory or parents")
}
return configPath, nil
}
// GetReposFromYAML reads the repos configuration from config.yaml
// Returns an empty ReposConfig if repos section doesn't exist
func GetReposFromYAML(configPath string) (*ReposConfig, error) {
data, err := os.ReadFile(configPath) // #nosec G304 - config file path from caller
if err != nil {
if os.IsNotExist(err) {
return &ReposConfig{}, nil
}
return nil, fmt.Errorf("failed to read config.yaml: %w", err)
}
// Parse into a generic map to extract repos section
var cfg map[string]interface{}
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("failed to parse config.yaml: %w", err)
}
repos := &ReposConfig{}
if reposRaw, ok := cfg["repos"]; ok && reposRaw != nil {
reposMap, ok := reposRaw.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("repos section is not a map")
}
if primary, ok := reposMap["primary"].(string); ok {
repos.Primary = primary
}View on GitHub (pinned to 71377f2769)
Solutions
- Check permissions: ls -l .beads/config.yaml and chmod u+r (or chown) as needed.
- Confirm the path is a file, not a directory: file .beads/config.yaml.
- If permissions were broken by a sudo-run command, re-own the .beads tree: sudo chown -R $(whoami) .beads.
Example fix
// before: config owned by root // after $ sudo chown -R $(whoami) .beads $ chmod 600 .beads/config.yaml
Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(configPath)
if err != nil {
return err
}
if fi.IsDir() {
return fmt.Errorf("%s is a directory, expected a file", configPath)
}
f, err := os.OpenFile(configPath, os.O_RDONLY, 0)
if err != nil {
return fmt.Errorf("cannot read config: %w", err)
}
f.Close() Try / catch
repos, err := config.GetReposFromYAML(configPath)
if err != nil && strings.Contains(err.Error(), "failed to read config.yaml") {
log.Printf("fix permissions on %s: %v", configPath, err)
} Prevention
- Avoid sudo-running bd commands that create .beads files.
- Keep config.yaml mode 0600 owned by your user.
- Pass a file path, never a directory, as configPath.
When it happens
Trigger: Calling GetReposFromYAML(configPath) (directly or via AddRepo/RemoveRepo/ListRepos) when os.ReadFile fails with e.g. EACCES (no read permission), EISDIR (configPath points at a directory), or I/O errors on the underlying storage.
Common situations: config.yaml owned by root or another user after a sudo-run init; .beads mounted with restrictive permissions; configPath mistakenly pointing to a directory; disk/network filesystem errors.
Related errors
- reading config: %w
- write metadata.json: %w
- failed to save config: %w
- failed to set beads.role config: %w
- failed to write config.yaml: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/023b2aa5fb884229.
Report an issue: GitHub.