gastownhall/beads · error

failed to read .gitignore: %w

Error message

failed to read .gitignore: %w

What it means

EnsureProjectGitignore reads the project's existing .gitignore so it can append only missing patterns. If os.ReadFile fails with any error other than NotExist (which is treated as 'no file yet'), it wraps and returns this error. It signals an unexpected filesystem problem, not a missing file.

Source

Thrown at cmd/bd/doctor/gitignore.go:774

		Status:  StatusOK,
		Message: "Dolt and credential files excluded",
	}
}

// EnsureProjectGitignore adds .dolt/, *.db, and .beads-credential-key patterns
// to the project-root .gitignore if they are not already present. Creates the
// file if it doesn't exist. This prevents users from accidentally committing
// Dolt database files or the credential encryption key.
// repoPath is the project root directory.
func EnsureProjectGitignore(repoPath string) error {
	gitignorePath := filepath.Join(repoPath, ".gitignore")

	var existingContent string
	// #nosec G304 -- path is hardcoded
	if content, err := os.ReadFile(gitignorePath); err == nil {
		existingContent = string(content)
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to read .gitignore: %w", err)
	}

	var toAdd []string
	for _, pattern := range ProjectGitignorePatterns {
		if !containsGitignorePattern(existingContent, pattern) {
			toAdd = append(toAdd, pattern)
		}
	}

	if len(toAdd) == 0 {
		return nil // All patterns already present
	}

	newContent := existingContent
	if len(newContent) > 0 && !strings.HasSuffix(newContent, "\n") {
		newContent += "\n"
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check permissions: ls -la .gitignore and chmod u+r (or chown) so the running user can read it.
  2. If .gitignore is a directory, remove or rename it (mv .gitignore .gitignore.bak) and re-run bd doctor --fix.
  3. Run inside the correct repo directory; a wrong cwd can point gitignorePath at an unusable path.
  4. If on a network/odd filesystem, copy the repo locally and retry.

Example fix

// before
$ bd doctor --fix
Error: failed to read .gitignore: open /repo/.gitignore: is a directory
// after
$ mv -f .gitignore .gitignore.bak
$ bd doctor --fix
✓ .gitignore updated
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(gitignorePath)
if err != nil && !os.IsNotExist(err) {
    return fmt.Errorf("precheck: cannot stat .gitignore: %w", err)
}
if info != nil && info.IsDir() {
    return fmt.Errorf("precheck: .gitignore is a directory")
}

Try / catch

if _, err := doctor.EnsureProjectGitignore(dir); err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && errors.Is(perr.Err, syscall.EACCES) {
        // handle permission problem (chown/chmod or elevate)
    }
    return err
}

Prevention

When it happens

Trigger: os.ReadFile(gitignorePath) returns an error and !os.IsNotExist(err) — e.g. a .gitignore path that is a directory, or a permission-denied read.

Common situations: .gitignore exists but the process lacks read permission; .gitignore is actually a directory (often from a bad checkout or symlink); filesystem/ACL issues on network mounts; SELinux or sandbox policies blocking reads in CI containers.

Related errors


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