juanfont/headscale · error
creating directory %s: %w
Error message
creating directory %s: %w
What it means
Returned by util.EnsureDir when os.MkdirAll fails for any reason other than a permission error (wrapped with the directory path and the raw error). Typical causes include a path component being a regular file, I/O errors, or invalid path syntax.
Source
Thrown at hscontrol/util/file.go:59
modeStr := viper.GetString(key)
mode, err := strconv.ParseUint(modeStr, Base8, BitSize64)
if err != nil {
return PermissionFallback
}
return fs.FileMode(mode) //nolint:gosec // file mode is bounded by ParseUint
}
func EnsureDir(dir string) error {
if _, err := os.Stat(dir); os.IsNotExist(err) { //nolint:noinlineerr
err := os.MkdirAll(dir, PermissionFallback)
if err != nil {
if errors.Is(err, os.ErrPermission) {
return fmt.Errorf("%w: %s", ErrDirectoryPermission, dir)
}
return fmt.Errorf("creating directory %s: %w", dir, err)
}
}
return nil
}
View on GitHub (pinned to 565fd254d0)
Solutions
- Check whether any component of the path already exists as a file and remove or relocate it
- Free disk space or remount the volume read-write if the error is EROFS/ENOSPC
- Inspect the wrapped error text for the syscall reason (ENOTDIR, ENOSPC, EROFS) and fix the underlying filesystem state
Example fix
# before # /etc/headscale/certs is a regular file left by an old install # after sudo rm /etc/headscale/certs && sudo mkdir -p /etc/headscale/certs
Defensive patterns
Strategy: try-catch
Validate before calling
if fi, err := os.Stat(dir); err == nil && !fi.IsDir() {
return fmt.Errorf("path %s exists and is not a directory", dir)
} Try / catch
if err := util.EnsureDir(dir); err != nil {
if errors.Is(err, util.ErrDirectoryPermission) {
// ownership fix path
}
// inspect wrapped syscall error: ENOTDIR => collision with a file, ENOSPC => disk
return err
} Prevention
- Avoid path collisions between files and directories in config layouts
- Check disk space in container healthchecks before it becomes ENOSPC
- Clean old install artifacts before redeploying to the same paths
When it happens
Trigger: Calling EnsureDir where some component of dir already exists as a file (e.g. /var/lib/headscale is a file), extremely long paths, or ENOSPC/EROFS device errors during MkdirAll.
Common situations: A config pointing tls_cert_path or state storage under a path that collides with an existing file; disk-full conditions in containers; leftover artifacts from previous installations.
Related errors
- creating directory failed with permission error
- reading or creating Noise protocol private key: %w
- reading or creating DERP server private key: %w
- removing old socket file: %w
- setting up unix socket: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/2fd4410762da627e.
Report an issue: GitHub.