gastownhall/beads · error
fs: WriteProjectGitignore: workDir not set
Error message
fs: WriteProjectGitignore: workDir not set
What it means
WriteProjectGitignore manages bd-required patterns in the project root .gitignore. This sentinel error means the repository was built without a workDir, so bd has no project root to place the gitignore in. It is a wiring/configuration error, not a filesystem failure.
Source
Thrown at internal/storage/domain/fs/beads.go:145
}
var missing []string
for _, line := range strings.Split(template, "\n") {
trimmed := strings.TrimSpace(line)
if trimmed == "" || strings.HasPrefix(trimmed, "#") || have[trimmed] {
continue
}
missing = append(missing, trimmed)
}
return missing
}
func (r *beadsDirFSRepositoryImpl) BeadsGitignoreExists(ctx context.Context) (bool, error) {
return fileExists(filepath.Join(r.beadsDir, ".gitignore"), "fs: BeadsGitignoreExists")
}
func (r *beadsDirFSRepositoryImpl) WriteProjectGitignore(ctx context.Context) error {
if r.workDir == "" {
return fmt.Errorf("fs: WriteProjectGitignore: workDir not set")
}
if len(r.templates.ProjectGitignorePatterns) == 0 {
return fmt.Errorf("fs: WriteProjectGitignore: patterns not configured")
}
path := filepath.Join(r.workDir, ".gitignore")
// #nosec G304 -- path joined under bound workDir
existing, err := os.ReadFile(path)
if err != nil && !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("fs: WriteProjectGitignore: read: %w", err)
}
var toAdd []string
for _, pattern := range r.templates.ProjectGitignorePatterns {
if !containsLine(existing, pattern) {
toAdd = append(toAdd, pattern)
}
}
if len(toAdd) == 0 {View on GitHub (pinned to 71377f2769)
Solutions
- Construct the repository through its standard constructor, passing the project root/workDir option
- If wiring manually, set workDir to an absolute project path before calling the method
- Resolve the git root (git rev-parse --show-toplevel) and pass that as workDir when unsure
- Verify initialization order: workDir must be bound before any gitignore write is attempted
Example fix
// before
r := &beadsDirFSRepositoryImpl{beadsDir: dir} // workDir empty
r.WriteProjectGitignore(ctx) // workDir not set
// after
workDir, _ := gitRoot(ctx)
r := fsrepo.New(fsrepo.WithBeadsDir(dir), fsrepo.WithWorkDir(workDir))
r.WriteProjectGitignore(ctx) Defensive patterns
Strategy: validation
Validate before calling
type worker interface{ HasWorkDir() bool }
if w, ok := repo.(worker); !ok || !w.HasWorkDir() {
return errors.New("repo requires workDir before WriteProjectGitignore")
}
repo.WriteProjectGitignore(ctx) Type guard
func hasWorkDir(w string) bool { return w != "" } Try / catch
if err := repo.WriteProjectGitignore(ctx); err != nil {
if strings.Contains(err.Error(), "workDir not set") {
return fmt.Errorf("rebuild repository with fsrepo.WithWorkDir(gitRoot)")
}
return err
} Prevention
- Bind workDir at repository construction time, before any write calls
- Resolve the git root programmatically rather than assuming cwd
- In library/embedding contexts, pass the project root explicitly
- Add an early sanity call that fails fast when workDir is empty
When it happens
Trigger: Calling WriteProjectGitignore on a beadsDirFSRepositoryImpl whose workDir field is empty — the constructor was not given the project root.
Common situations: Programmatic use of the fs repository without WithWorkDir-style option; tests instantiating the impl directly; embedding bd as a library without resolving the project root first.
Related errors
- fs: WriteBeadsGitignore: template not configured
- fs: WriteProjectGitignore: patterns not configured
- %w: issue_prefix config is missing (run 'bd init --prefix <p
- multiple .doltcfg directories detected
- dolt directory is required
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/76eda0a88e020dd1.
Report an issue: GitHub.