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 true

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix write permissions: sudo chown $(whoami) .gitignore or chmod u+w .gitignore.
  2. Ensure the repo/filesystem is writable (not a read-only mount or CI artifact checkout).
  3. Free disk space if the filesystem is full (df -h).
  4. 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

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


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