juanfont/headscale · error
reading logs directory: %w
Error message
reading logs directory: %w
What it means
Returned by cleanupSuccessfulTestArtifacts when os.ReadDir on the control_logs directory fails. Filesystem-level causes: the directory does not exist (no runs recorded yet), permission denied, or the path is not a directory. It propagates from `hi cleanup` when pruning artifacts of successful runs.
Source
Thrown at cmd/hi/cleanup.go:342
fmt.Printf("Removed Go module cache volume: %s\n", volumeName)
}
return nil
}
// cleanupSuccessfulTestArtifacts removes artifacts from successful test runs to save disk space.
// This function removes large artifacts that are mainly useful for debugging failures:
// - Database dumps (.db files)
// - Profile data (pprof directories)
// - MapResponse data (mapresponses directories)
// - Prometheus metrics files
//
// It preserves:
// - Log files (.log) which are small and useful for verification.
func cleanupSuccessfulTestArtifacts(logsDir string, verbose bool) error {
entries, err := os.ReadDir(logsDir)
if err != nil {
return fmt.Errorf("reading logs directory: %w", err)
}
var (
removedFiles, removedDirs int
totalSize int64
)
for _, entry := range entries {
name := entry.Name()
fullPath := filepath.Join(logsDir, name)
if entry.IsDir() {
// Remove pprof and mapresponses directories (typically large)
// These directories contain artifacts from all containers in the test run
if name == "pprof" || name == "mapresponses" {
size, sizeErr := getDirSize(fullPath)
if sizeErr == nil {
totalSize += sizeView on GitHub (pinned to 565fd254d0)
Solutions
- Check that the logs directory exists and is readable: ls control_logs/
- Create it or run one integration test first so it gets populated
- Fix ownership/permissions (chown/chmod) if tests ran as another user
- Remove blocking non-directory entries at the expected path
Example fix
# before: no runs yet, directory absent go run ./cmd/hi cleanup # reading logs directory: ... # after mkdir -p control_logs go run ./cmd/hi cleanup
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the logs dir exists and is a directory before cleanup.
if fi, err := os.Stat(logsDir); err != nil {
fmt.Fprintln(os.Stderr, "no logs directory yet — nothing to clean")
return nil
} else if !fi.IsDir() {
return fmt.Errorf("%s is not a directory", logsDir)
} Type guard
func isReadableDir(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.IsDir()
} Try / catch
Treat os.IsNotExist(err) from ReadDir as a no-op (nothing to clean); other errors (permission) should be reported with the path.
Prevention
- Create control_logs/ as part of workspace setup
- Keep ownership consistent — avoid mixing sudo and user-run tests
- Run at least one integration test before expecting cleanup to find artifacts
When it happens
Trigger: Running artifact cleanup when the logs directory was deleted or never created (no prior test runs); insufficient permissions on control_logs; a file existing where the directory is expected.
Common situations: Fresh checkouts before any integration run; CI workspaces wiped between jobs; directories removed by disk-cleanup scripts; ownership mismatches after running tests as root and cleaning as user.
Related errors
- cleaning stale test containers: %w
- getting absolute path for logs directory: %w
- creating logs directory: %w
- creating directory failed with permission error
- creating temp dir: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/316e9dfabd8d7b16.
Report an issue: GitHub.