gastownhall/beads · error
reading legacy config: %w
Error message
reading legacy config: %w
What it means
Load wraps a non-ENOENT os.ReadFile failure of the legacy .beads/config.json with "reading legacy config: %w". A missing legacy file is treated as no legacy config; this error means the file exists but is unreadable, blocking the migrate-to-metadata.json path.
Source
Thrown at internal/configfile/configfile.go:94
}
func ConfigPath(beadsDir string) string {
return filepath.Join(beadsDir, ConfigFileName)
}
func Load(beadsDir string) (*Config, error) {
configPath := ConfigPath(beadsDir)
data, err := os.ReadFile(configPath) // #nosec G304 - controlled path from config
if os.IsNotExist(err) {
// Try legacy config.json location (migration path)
legacyPath := filepath.Join(beadsDir, "config.json")
data, err = os.ReadFile(legacyPath) // #nosec G304 - controlled path from config
if os.IsNotExist(err) {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("reading legacy config: %w", err)
}
// Migrate: parse legacy config, save as metadata.json, remove old file
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("parsing legacy config: %w", err)
}
// Save to new location
if err := cfg.Save(beadsDir); err != nil {
return nil, fmt.Errorf("migrating config to metadata.json: %w", err)
}
// Remove legacy file (best effort: migration already saved to new location)
_ = os.Remove(legacyPath)
return &cfg, nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Fix permissions: `chmod u+r .beads/config.json` and confirm ownership
- Verify it is a regular file, not a directory or symlink to a missing target
- If the migration already completed, the legacy file can be archived/removed after confirming metadata.json exists
Example fix
// before -rw------- root config.json # owned by root, unreadable // after sudo chown $USER .beads/config.json && chmod u+rw .beads/config.json
Defensive patterns
Strategy: try-catch
Validate before calling
fi, err := os.Stat(filepath.Join(".beads", "config.json"))
if err == nil && (!fi.Mode().IsRegular() || fi.Mode().Perm()&0o400 == 0) {
// legacy config unreadable: fix permissions before running bd
} Try / catch
cfg, err := bd.Load(cfgOpts)
if err != nil {
if errors.Is(err, fs.ErrPermission) { /* chown/chmod .beads/config.json */ }
return err
} Prevention
- Preserve ownership/permissions when copying or restoring .beads directories
- Complete the legacy->metadata.json migration once, then remove config.json deliberately
- Check workspace file ownership after running bd as root/sudo
When it happens
Trigger: Load(config) when .beads/config.json exists but cannot be read — permission denied, it is a directory, or an I/O error occurs during the migration check.
Common situations: Legacy config left read-only after copying a workspace as another user; config.json partially restored from backup with broken permissions; disk/device errors.
Related errors
- migrating config to metadata.json: %w
- write metadata.json: %w
- %s: %w
- failed to save config: %w
- failed to open JSONL: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b79ebe72b84ec681.
Report an issue: GitHub.