{"record":{"id":"98546db33ce788fe","repo":"gastownhall/beads","slug":"fs-writebeadsgitignore-template-not-configured","errorCode":null,"errorMessage":"fs: WriteBeadsGitignore: template not configured","messagePattern":"fs: WriteBeadsGitignore: template not configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/fs/beads.go","lineNumber":89,"sourceCode":"\t\treturn fmt.Errorf(\"fs: CreateBeadsDir: fix perms %s: %w\", r.beadsDir, err)\n\t}\n\treturn nil\n}\n\nfunc (r *beadsDirFSRepositoryImpl) BeadsDirExists(ctx context.Context) (bool, error) {\n\tinfo, err := os.Stat(r.beadsDir)\n\tif errors.Is(err, os.ErrNotExist) {\n\t\treturn false, nil\n\t}\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"fs: BeadsDirExists: stat %s: %w\", r.beadsDir, err)\n\t}\n\treturn info.IsDir(), nil\n}\n\nfunc (r *beadsDirFSRepositoryImpl) WriteBeadsGitignore(ctx context.Context) error {\n\tif r.templates.BeadsGitignore == \"\" {\n\t\treturn fmt.Errorf(\"fs: WriteBeadsGitignore: template not configured\")\n\t}\n\tpath := filepath.Join(r.beadsDir, \".gitignore\")\n\t// #nosec G304 -- path joined under bound beadsDir\n\texisting, err := os.ReadFile(path)\n\tif errors.Is(err, os.ErrNotExist) {\n\t\tif werr := os.WriteFile(path, []byte(r.templates.BeadsGitignore), 0600); werr != nil {\n\t\t\treturn fmt.Errorf(\"fs: WriteBeadsGitignore: %w\", werr)\n\t\t}\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fs: WriteBeadsGitignore: read: %w\", err)\n\t}\n\t// Existing file: append-only. A wholesale rewrite to the template\n\t// destroys local rules (e.g. export negations) the user added — the\n\t// gitignore is shared state, not bd-owned (bd-kaaz3).\n\tmissing := missingTemplatePatternLines(string(existing), r.templates.BeadsGitignore)\n\tif len(missing) == 0 {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/fs/beads.go#L71-L107","documentation":"WriteBeadsGitignore writes bd's required ignore patterns into .beads/.gitignore. This sentinel error means the repository was constructed without the BeadsGitignore template configured, so there is nothing to write. It is a programming/configuration error in the fs repository wiring, not a filesystem problem.","triggerScenarios":"Calling WriteBeadsGitignore on a beadsDirFSRepositoryImpl whose templates.BeadsGitignore field is empty — i.e. the repository was constructed without providing the embedded template set.","commonSituations":"Custom repository construction that forgot to pass the templates/embedded assets; tests instantiating the impl directly with a zero-value templates struct; a build tag or embed failure leaving templates empty.","solutions":["Construct the repository through its normal constructor/factory so the embedded templates are loaded","If constructing manually, set templates.BeadsGitignore to the bundled template content before calling the method","Check embed directives/assets are present in the build (no stubbed template source)","Update out-of-date local code that predates the templates field requirement"],"exampleFix":"// before\nr := &beadsDirFSRepositoryImpl{beadsDir: dir} // templates zero-value\nr.WriteBeadsGitignore(ctx) // template not configured\n// after\nr := fsrepo.New(fsrepo.WithBeadsDir(dir), fsrepo.WithDefaultTemplates())\nr.WriteBeadsGitignore(ctx)","handlingStrategy":"validation","validationCode":"type templated interface{ Templates() Templates }\nif t, ok := repo.(templated); ok && t.Templates().BeadsGitignore == \"\" {\n\treturn errors.New(\"repo built without BeadsGitignore template\")\n}\nrepo.WriteBeadsGitignore(ctx)","typeGuard":"func hasGitignoreTemplate(t Templates) bool { return t.BeadsGitignore != \"\" }","tryCatchPattern":"if err := repo.WriteBeadsGitignore(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"template not configured\") {\n\t\treturn fmt.Errorf(\"repository misconfigured: rebuild via fsrepo.New with default templates\")\n\t}\n\treturn err\n}","preventionTips":["Always construct the fs repository through its exported constructor, never raw struct literals","In tests, use the same factory the CLI uses","Keep template embed assets in sync when refactoring","Add a constructor invariant that fails fast on empty templates"],"tags":["configuration","templates","initialization"],"backgroundTag":"missing-template-config","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}