gastownhall/beads · error

cannot stat default.nix

Error message

cannot stat default.nix: %v

What it means

fixNixHash repairs the vendorHash in default.nix by rewriting the file. The first step is os.Stat("default.nix") to capture the file's permissions for the later rewrite; if the file cannot be stat'ed (typically because it does not exist in the current working directory), this error wraps the underlying os error.

Solutions

  1. cd to the repository root (where default.nix lives) and re-run `bd fix`
  2. Verify default.nix exists: `ls -la default.nix` — recreate or restore it from git if missing
  3. Check directory permissions if the path exists but stat still fails

Example fix

// before
$ cd cmd/bd && bd fix
cannot stat default.nix: stat default.nix: no such file or directory
// after
$ cd /path/to/repo && bd fix
Defensive patterns

Strategy: validation

Validate before calling

[ -f default.nix ] || { echo "run from repo root where default.nix lives"; exit 1; }

Try / catch

out, err := exec.Command("bd", "fix").CombinedOutput()
if err != nil && strings.Contains(string(out), "cannot stat default.nix") {
    // cd to repo root or restore default.nix, then retry
}

Prevention

When it happens

Trigger: Running `bd fix` from a directory where default.nix does not exist (repo root expected), or where the path exists but is unreadable at the directory level (permissions), or a symlink pointing to nothing.

Common situations: Executing `bd fix` from a subdirectory instead of the repository root; a broken default.nix symlink; renamed/deleted default.nix after switching build systems.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at cmd/bd/preflight.go:755

	cmd2 := exec.Command("git", "diff", "--name-only", "--cached", "--", "go.sum")
	out2, _ := cmd2.Output()
	if len(strings.TrimSpace(string(out1))) == 0 && len(strings.TrimSpace(string(out2))) == 0 {
		return false, "", "", nil
	}

	if _, err := exec.LookPath("nix"); err != nil {
		return false, "", "", fmt.Errorf(
			"nix not found in PATH\n  Manual fix:\n" +
				"    1. Edit default.nix: set vendorHash = \"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\"\n" +
				"    2. Run: nix build .#default\n" +
				"    3. Copy the 'got:' hash from the error into default.nix",
		)
	}

	nixPath := "default.nix"
	nixInfo, err := os.Stat(nixPath)
	if err != nil {
		return false, "", "", fmt.Errorf("cannot stat default.nix: %v", err)
	}
	nixPerm := nixInfo.Mode().Perm()

	content, err := os.ReadFile(nixPath)
	if err != nil {
		return false, "", "", fmt.Errorf("cannot read default.nix: %v", err)
	}

	re := regexp.MustCompile(`(vendorHash\s*=\s*)"([^"]+)"`)
	loc := re.FindSubmatchIndex(content)
	if loc == nil {
		return false, "", "", fmt.Errorf("vendorHash not found in default.nix")
	}
	oldHash := string(content[loc[4]:loc[5]])

	const sentinel = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
	probed := append(append([]byte{}, content[:loc[4]]...), append([]byte(sentinel), content[loc[5]:]...)...)
	if err := os.WriteFile(nixPath, probed, nixPerm); err != nil {

View on GitHub (pinned to 71377f2769)