gastownhall/beads · error

failed to find config.yaml: %w

Error message

failed to find config.yaml: %w

What it means

Wraps an error from config.FindConfigYAMLPath() during contributor wizard step 4b, which locates the global/user config.yaml that holds multi-repo hydration settings. Thrown when the function cannot resolve a config.yaml path (e.g. it cannot determine the home/config directory or an I/O error occurs while searching).

Source

Thrown at cmd/bd/init_contributor.go:224

	fmt.Printf("\n%s Configuring contributor auto-routing...\n", ui.RenderAccent("▶"))

	// Set routing config (canonical namespace per internal/config/config.go)
	if err := store.SetConfig(ctx, "routing.mode", "auto"); err != nil {
		return fmt.Errorf("failed to set routing mode: %w", err)
	}
	if err := store.SetConfig(ctx, "routing.contributor", planningPath); err != nil {
		return fmt.Errorf("failed to set routing contributor path: %w", err)
	}

	fmt.Printf("%s Auto-routing enabled\n", ui.RenderPass("✓"))

	// Step 4b: Enable multi-repo hydration so routed issues are visible (bd-fix-routing)
	fmt.Printf("\n%s Configuring multi-repo hydration...\n", ui.RenderAccent("▶"))

	// Find config.yaml path
	configPath, err := config.FindConfigYAMLPath()
	if err != nil {
		return fmt.Errorf("failed to find config.yaml: %w", err)
	}

	// Add planning repo to repos.additional for hydration
	if err := config.AddRepo(configPath, planningPath); err != nil {
		// Check if already added (non-fatal)
		if !strings.Contains(err.Error(), "already exists") {
			return fmt.Errorf("failed to configure hydration: %w", err)
		}
	}

	fmt.Printf("%s Hydration enabled for planning repo\n", ui.RenderPass("✓"))
	fmt.Println("  Issues from planning repo will appear in 'bd list'")

	// If this is a fork, configure sync to pull beads from upstream (bd-bx9)
	// This ensures `bd dolt pull` gets the latest issues from the source repo,
	// not from the fork's potentially outdated origin/main
	if isFork {
		if err := store.SetConfig(ctx, "sync.remote", "upstream"); err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure HOME (or XDG_CONFIG_HOME) points to an existing, writable directory before running bd init --contributor
  2. Create the expected config directory (e.g. ~/.config/beads) and retry
  3. Run outside of stripped-down environments (containers/cron) where HOME is unset
  4. Inspect the wrapped error to see which path lookup failed

Example fix

// before
$ sudo bd init --contributor
// after
$ bd init --contributor   # run as the normal user so HOME resolves correctly
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: HOME/config dir must exist and be writable
home, err := os.UserHomeDir()
if err != nil || home == "" {
	return fmt.Errorf("HOME must be set and resolvable: %w", err)
}
if err := os.MkdirAll(filepath.Dir(defaultConfigPath), 0750); err != nil {
	return fmt.Errorf("config dir not creatable: %w", err)
}

Try / catch

if err := runContributorWizard(ctx, store, ...); err != nil {
	if strings.Contains(err.Error(), "failed to find config.yaml") {
		fmt.Fprintln(os.Stderr, "Set HOME/XDG_CONFIG_HOME to an existing writable directory and retry")
	}
	return err
}

Prevention

When it happens

Trigger: config.FindConfigYAMLPath() returns an error inside runContributorWizard — e.g. os.UserHomeDir or XDG config lookup fails, or the search encounters an unreadable directory.

Common situations: HOME not set or pointing at a non-writable path when running under sudo/CI containers; unusual XDG_CONFIG_HOME; filesystem errors in the config search path.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/3e9bd0b08e15a8ff. Report an issue: GitHub.