juanfont/headscale · error
creating logs directory: %w
Error message
creating logs directory: %w
What it means
Returned by runTestContainer when os.MkdirAll(absLogsDir, 0o755) fails while creating control_logs/<runID>. Filesystem causes: a parent directory owned by another user (permission denied), a non-directory file occupying part of the path, or read-only filesystem. Distinct from error 298: here the absolute path resolved fine but creation failed.
Source
Thrown at cmd/hi/docker.go:62
runID := dockertestutil.GenerateRunID()
containerName := "headscale-test-suite-" + runID
logsDir := filepath.Join(config.LogsDir, runID)
if config.Verbose {
log.Printf("Run ID: %s", runID)
log.Printf("Container name: %s", containerName)
log.Printf("Logs directory: %s", logsDir)
}
absLogsDir, err := filepath.Abs(logsDir)
if err != nil {
return fmt.Errorf("getting absolute path for logs directory: %w", err)
}
const dirPerm = 0o755
if err := os.MkdirAll(absLogsDir, dirPerm); err != nil { //nolint:noinlineerr
return fmt.Errorf("creating logs directory: %w", err)
}
if config.CleanBefore {
if config.Verbose {
log.Printf("Running pre-test cleanup...")
}
err := cleanupBeforeTest(ctx)
if err != nil && config.Verbose {
log.Printf("Warning: pre-test cleanup failed: %v", err)
}
}
goTestCmd := buildGoTestCommand(config)
if config.Verbose {
log.Printf("Command: %s", strings.Join(goTestCmd, " "))
}
View on GitHub (pinned to 565fd254d0)
Solutions
- Inspect the path: ls -ld control_logs — confirm it is a directory you can write
- Fix ownership: sudo chown -R $USER control_logs (common after root runs)
- Remove any file occupying the directory name: rm control_logs if it is a regular file
- Check disk space and mount options (read-only workspace) in CI
Example fix
# before: root-owned logs dir from an earlier sudo run ls -ld control_logs # drwxr-xr-x root root go run ./cmd/hi run TestACL # creating logs directory: permission denied # after sudo chown -R "$USER" control_logs go run ./cmd/hi run TestACL
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the logs root is a writable directory before test runs.
const perm = 0o755
if err := os.MkdirAll("control_logs", perm); err != nil {
log.Fatalf("cannot create logs dir: %v", err)
}
if fi, err := os.Stat("control_logs"); err != nil || !fi.IsDir() {
log.Fatal("control_logs exists but is not a directory")
} Type guard
func isWritableDir(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.IsDir() && fi.Mode().Perm()&0o200 != 0
} Try / catch
Inspect the wrapped error: os.IsPermission → fix ownership/permissions; os.IsExist with a non-directory → remove the blocking file; read-only filesystem → remount or relocate LogsDir.
Prevention
- Never mix sudo and non-sudo test runs in the same workspace
- Add control_logs to .gitignore and pre-create it in setup scripts
- On CI, ensure the workspace mount is read-write
- Check disk space before large test sessions
When it happens
Trigger: control_logs (or a path component) exists as a regular file; the repo is on a read-only mount; earlier runs done as root left root-owned directories; disk quota exhausted.
Common situations: Mixing sudo and non-sudo test runs creating root-owned control_logs; CI containers mounting the workspace read-only; a stray file named control_logs; full disks or quotas.
Related errors
- creating directory failed with permission error
- reading logs directory: %w
- getting absolute path for logs directory: %w
- writing stdout log: %w
- writing stderr log: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/c2770eb1d40c8a4f.
Report an issue: GitHub.