gastownhall/beads · error
failed to write .gitignore: %w
Error message
failed to write .gitignore: %w
What it means
After computing which ProjectGitignorePatterns are missing, EnsureProjectGitignore writes the updated content with os.WriteFile (mode 0644). Any write failure is wrapped in this error. It means the tool read the file fine but could not persist the updated .gitignore.
Source
Thrown at cmd/bd/doctor/gitignore.go:800
}
if len(toAdd) == 0 {
return nil // All patterns already present
}
newContent := existingContent
if len(newContent) > 0 && !strings.HasSuffix(newContent, "\n") {
newContent += "\n"
}
newContent += "\n" + ProjectGitignoreHeader + "\n"
for _, pattern := range toAdd {
newContent += pattern + "\n"
}
// #nosec G306 -- gitignore needs to be readable by git and collaborators
if err := os.WriteFile(gitignorePath, []byte(newContent), 0644); err != nil {
return fmt.Errorf("failed to write .gitignore: %w", err)
}
return nil
}
// FixProjectGitignore is an alias for EnsureProjectGitignore, used by bd doctor --fix.
// repoPath is the project root directory.
func FixProjectGitignore(repoPath string) error {
return EnsureProjectGitignore(repoPath)
}
// containsGitignorePattern checks if a gitignore file content contains the given pattern.
// It checks for the pattern as a standalone line (ignoring leading/trailing whitespace).
func containsGitignorePattern(content, pattern string) bool {
for _, line := range strings.Split(content, "\n") {
line = strings.TrimSpace(line)
if line == pattern {
return trueView on GitHub (pinned to 71377f2769)
Solutions
- Fix write permissions: sudo chown $(whoami) .gitignore or chmod u+w .gitignore.
- Ensure the repo/filesystem is writable (not a read-only mount or CI artifact checkout).
- Free disk space if the filesystem is full (df -h).
- If .gitignore is a directory, replace it with a regular file and retry.
Example fix
// before $ bd doctor --fix Error: failed to write .gitignore: open /repo/.gitignore: permission denied // after $ chmod u+w .gitignore # or: sudo chown $(whoami) .gitignore $ bd doctor --fix ✓ .gitignore updated
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(gitignorePath)
if err == nil && info.IsDir() {
return fmt.Errorf("precheck: .gitignore is a directory, not a file")
}
if f, err := os.OpenFile(gitignorePath, os.O_WRONLY|os.O_CREATE, 0644); err != nil {
return fmt.Errorf("precheck: .gitignore not writable: %w", err)
} else {
f.Close()
} Try / catch
if err := doctor.EnsureProjectGitignore(dir); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && (errors.Is(perr.Err, syscall.EACCES) || errors.Is(perr.Err, syscall.EROFS)) {
// prompt for elevation or switch to a writable checkout
}
return err
} Prevention
- Run bd doctor --fix with write access to the repo (avoid root-owned checkouts).
- Use rw checkouts in CI when automated fixes are expected.
- Monitor disk space before running write-heavy maintenance.
- Keep .gitignore a regular file owned by the working user.
When it happens
Trigger: os.WriteFile(gitignorePath, []byte(newContent), 0644) returns a non-nil error — permission denied, read-only filesystem, disk full, or the target path is a directory.
Common situations: Running bd doctor --fix in a repo owned by root or another user; read-only CI checkout; disk-full; .gitignore replaced by a directory; immutable attribute set on the file.
Related errors
- fs: WriteBeadsGitignore: %w
- ensure .beads/.gitignore: %w
- read .beads/.gitignore: %w
- failed to read .gitignore: %w
- failed to write user config.yaml: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/15459a1ecaedaf5b.
Report an issue: GitHub.