gastownhall/beads · error

scanning artifacts at %s: %w

Error message

scanning artifacts at %s: %w

What it means

ScanForArtifacts wraps errors returned by filepath.WalkDir while scanning the repository tree for leftover SQLite artifacts, cruft .beads directories, and redirect issues. It reports that the filesystem walk itself failed (not an individual file finding).

Source

Thrown at cmd/bd/doctor/artifacts.go:129

		// Skip node_modules and similar
		if info.IsDir() && (base == "node_modules" || base == "vendor" || base == "__pycache__") {
			return filepath.SkipDir
		}

		// We only care about directories named ".beads"
		if !info.IsDir() || base != ".beads" {
			return nil
		}

		// Found a .beads directory - scan it
		scanBeadsDir(path, &report)

		// Don't descend into .beads/ itself (we've scanned it)
		return filepath.SkipDir
	})
	if walkErr != nil {
		return report, fmt.Errorf("scanning artifacts at %s: %w", rootPath, walkErr)
	}

	report.TotalCount = len(report.SQLiteArtifacts) +
		len(report.CruftBeadsDirs) + len(report.RedirectIssues)

	for _, findings := range [][]ArtifactFinding{
		report.SQLiteArtifacts,
		report.CruftBeadsDirs, report.RedirectIssues,
	} {
		for _, f := range findings {
			if f.SafeDelete {
				report.SafeDeleteCount++
			}
		}
	}

	return report, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix permissions on unreadable directories reported in the wrapped error (chmod/chown or run with adequate privileges)
  2. Remove or repair broken symlinks in the tree being scanned
  3. Exclude exotic mounts from the scan by running bd doctor inside the project directory rather than above it
  4. Retry after fixing; then re-run `bd doctor` to confirm the artifact scan completes

Example fix

// before
chmod 000 ./node_modules/.cache/locked-dir
// after
chmod u+rX ./node_modules/.cache/locked-dir
Defensive patterns

Strategy: retry

Validate before calling

import "os"
func canWalk(root string) error {
	return filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error {
		if err != nil { return err }
		if d.IsDir() {
			if f, ferr := os.Open(p); ferr != nil { return ferr } else { f.Close() }
		}
		return nil
	})
}

Try / catch

report, err := ScanForArtifacts(root)
if err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) {
		log.Printf("scan blocked at %s: %v — fix perms and retry", pe.Path, pe.Err)
	}
	return err
}

Prevention

When it happens

Trigger: ScanForArtifacts (via CheckClassicArtifacts during `bd doctor`) when filepath.WalkDir returns a non-SkipDir error — e.g. unreadable directories, permission-denied on a subtree, symlink loops, or deleted dirs mid-walk — at cmd/bd/doctor/artifacts.go:129.

Common situations: Scanning a repo containing root-owned or permission-restricted directories, a broken/looping symlink, or a network mount that drops out during the walk; also from tests that feed ScanForArtifacts odd fixture trees.

Related errors


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