gastownhall/beads · error

not a beads workspace: .beads directory not found for %s

Error message

not a beads workspace: .beads directory not found for %s

What it means

After resolving the workspace's beads directory (via beads.ResolveBeadsDirForRepo), resolveWorkspaceBeadsDirs stats it and requires it to be an existing directory. If .beads is missing or is not a directory, this error declares the path is not a beads workspace and callers like validateBeadsWorkspace and Permissions refuse to operate.

Source

Thrown at cmd/bd/doctor/fix/common.go:78

// attempting any fix operations. This prevents path traversal attacks.
func validateBeadsWorkspace(path string) error {
	_, err := resolveWorkspaceBeadsDirs(path)
	return err
}

func resolveWorkspaceBeadsDirs(path string) (workspaceBeadsDirs, error) {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return workspaceBeadsDirs{}, fmt.Errorf("invalid path: %w", err)
	}

	dirs := workspaceBeadsDirs{
		local:    filepath.Join(absPath, ".beads"),
		resolved: beads.ResolveBeadsDirForRepo(absPath),
	}

	if info, err := os.Stat(dirs.resolved); err != nil || !info.IsDir() {
		return workspaceBeadsDirs{}, fmt.Errorf("not a beads workspace: .beads directory not found for %s", absPath)
	}

	return dirs, nil
}

func resolvedWorkspaceBeadsDir(path string) (string, error) {
	dirs, err := resolveWorkspaceBeadsDirs(path)
	if err != nil {
		return "", err
	}

	return dirs.resolved, nil
}

func localWorkspaceBeadsDir(path string) (string, error) {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return "", fmt.Errorf("invalid path: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Initialize the workspace: run `bd init` in the repo root to create .beads.
  2. Verify you are passing the correct workspace root (the directory containing .beads).
  3. Check that the resolved .beads path exists and is a directory: `ls -la <repo>/.beads`.
  4. Restore .beads from backup or re-import from .beads/issues.jsonl if it was deleted.

Example fix

// before
fix.Permissions("/home/me/not-a-repo")  // not a beads workspace
// after
bd init /home/me/repo                    // creates .beads
fix.Permissions("/home/me/repo")
Defensive patterns

Strategy: validation

Validate before calling

resolved := beads.ResolveBeadsDirForRepo(repoRoot)
if fi, err := os.Stat(resolved); err != nil || !fi.IsDir() {
	// run `bd init` in repoRoot before calling doctor fixes
}

Try / catch

if err := fix.Permissions(path); err != nil && strings.Contains(err.Error(), "not a beads workspace") {
	// initialize the workspace, then retry
	return fmt.Errorf("run `bd init` in %s: %w", path, err)
}

Prevention

When it happens

Trigger: os.Stat(resolved) fails or returns a non-directory in resolveWorkspaceBeadsDirs (cmd/bd/doctor/fix/common.go:78) — running doctor fix commands outside any initialized bd repo, or a .beads path that is a file/symlink target that vanished.

Common situations: Running `bd doctor` fix subcommands in a repo where `bd init` was never run; wrong repo root passed (parent directory instead of the workspace); .beads accidentally deleted or replaced by a file; submodule/monorepo layouts where beads dir resolution picks a parent without .beads.

Related errors


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