gastownhall/beads · error
%s: %w
Error message
%s: %w
What it means
findParentConfig walks up from a start directory looking for a `.beads` config, and wraps any error from configfile.LoadForDiscovery with the candidate config path via `%s: %w`. It exists so users can see exactly which `.beads` config file failed to load during ancestor-directory discovery. The wrapped error typically indicates a corrupt or unreadable config JSON.
Source
Thrown at cmd/bd/bootstrap.go:1058
}
// findParentConfig walks up from beadsDir's parent looking for a
// .beads/metadata.json in ancestor directories. This handles the case where a
// rig subdirectory (its own git repo) doesn't have a local .beads but its
// parent workspace does. Returns nil if no parent config is found. A malformed
// or unreadable ancestor metadata file is authoritative and returned as an error;
// bootstrap must not skip it and select a more distant workspace or defaults.
func findParentConfig(beadsDir string) (*configfile.Config, error) {
// Start from the parent of beadsDir's enclosing directory.
// beadsDir is typically "<project>/.beads", so we start from <project>'s parent.
start := filepath.Dir(filepath.Dir(beadsDir))
homeDir, _ := os.UserHomeDir()
for dir := start; dir != "/" && dir != "."; {
candidate := filepath.Join(dir, ".beads")
cfg, err := configfile.LoadForDiscovery(candidate)
if err != nil {
return nil, fmt.Errorf("%s: %w", configfile.ConfigPath(candidate), err)
}
if cfg != nil {
if err := guardLegacyUpgradeWorkspace(candidate); err != nil {
return nil, err
}
return cfg, nil
}
// Don't search above $HOME
if homeDir != "" && dir == homeDir {
break
}
parent := filepath.Dir(dir)
if parent == dir {
break
}
dir = parentView on GitHub (pinned to 71377f2769)
Solutions
- Open the path named in the error message and fix or validate the .beads config JSON (e.g. `jq . .beads/config.json`).
- If the ancestor config is stale/unwanted, delete or repair that `.beads` directory.
- Restore read permissions on the config file (chmod/chown).
- Re-run the command; if discovery should skip corrupt ancestors, note existing tests cover TestFindParentConfigDoesNotSkipCorruptNearestAncestor behavior.
Example fix
// before: corrupt config discovered /home/user/proj/.beads/config.json: unexpected end of JSON input // after: repair the file jq . /home/user/proj/.beads/config.json # find the syntax error, fix it
Defensive patterns
Strategy: try-catch
Validate before calling
if [ -f .beads/config.json ]; then jq -e . .beads/config.json >/dev/null || echo 'corrupt config'; fi
Type guard
func validBeadsConfig(dir string) bool {
_, err := configfile.LoadForDiscovery(filepath.Join(dir, ".beads"))
return err == nil
} Try / catch
cfg, err := findParentConfig(start)
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) { /* handle unreadable path */ }
return fmt.Errorf("bootstrap discovery failed: %w", err)
} Prevention
- Validate .beads/config.json with jq after editing
- Never hand-edit configs without a backup
- Watch for disk-full/crash truncation of config writes
When it happens
Trigger: Running bd commands in (or under) a directory where some ancestor directory has a `.beads/config.json` that fails to load — malformed JSON, unreadable permissions, or a corrupt file — while findParentConfig walks up from the working directory.
Common situations: A partially-written or hand-edited .beads/config.json; a config file truncated by a crashed process or disk-full; wrong file permissions after copying a repo as root; running inside a worktree or subdir where an ancestor's stale config is corrupt.
Related errors
- write metadata.json: %w
- failed to save config: %w
- failed to set beads.role config: %w
- failed to find config.yaml: %w
- failed to write config.yaml: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a3cbc9c5714dad78.
Report an issue: GitHub.