kubernetes/kops · error
failed to ensure the directory: %s, error: %w
Error message
failed to ensure the directory: %s, error: %w
What it means
During the volume-mount phase of nodeup, Build() iterates NodeupConfig.VolumeMounts and, for each mount, ensures the target directory exists via b.EnsureDirectory before formatting/mounting the device. If directory creation fails (permissions, non-empty mountpoint conflicts, read-only root filesystem, I/O error), the error is wrapped as 'failed to ensure the directory'.
Source
Thrown at nodeup/pkg/model/volumes.go:49
*NodeupModelContext
}
var _ fi.NodeupModelBuilder = &VolumesBuilder{}
// Build is responsible for handling the mounting additional volumes onto the instance
func (b *VolumesBuilder) Build(c *fi.NodeupModelBuilderContext) error {
// @step: check if the instancegroup has any volumes to mount
if !b.UseVolumeMounts() {
klog.V(1).Info("Skipping the volume builder, no volumes defined for this instancegroup")
return nil
}
// @step: iterate the volume mounts and attempt to mount the devices
for _, x := range b.NodeupConfig.VolumeMounts {
// @check the directory exists, else create it
if err := b.EnsureDirectory(x.Path); err != nil {
return fmt.Errorf("failed to ensure the directory: %s, error: %w", x.Path, err)
}
m := &mount.SafeFormatAndMount{
Exec: utilexec.New(),
Interface: mount.New(""),
}
// @check if the device is already mounted
if found, err := b.IsMounted(m, x.Device, x.Path); err != nil {
return fmt.Errorf("failed to check if device %q is mounted, error: %w", x.Device, err)
} else if found {
klog.V(3).Infof("Skipping device: %s, path: %s as already mounted", x.Device, x.Path)
continue
}
klog.Infof("Attempting to format and mount device: %s, path: %s", x.Device, x.Path)
if err := m.FormatAndMount(x.Device, x.Path, x.Filesystem, x.MountOptions); err != nil {View on GitHub (pinned to 4c8573c808)
Solutions
- Check the wrapped inner error with `klog`/journalctl on the node (nodeup logs) to see the exact mkdir failure reason (EACCES/EROFS/EEXIST/ENOSPC).
- Remove or rename any non-directory file already existing at the VolumeMounts Path: `ls -la /path`, fix, then rerun nodeup.
- Free disk space or remount the root filesystem read-write if ENOSPC/EROFS is reported.
- Correct the volumeMounts path in the cluster spec so it points to a valid mountpoint location, then run `kops update cluster` and re-bootstrap the node.
Example fix
// before: path is an existing regular file, mkdir fails volumeMounts: - device: /dev/nvme1n1 path: /data/file.txt // after: point the mount at a directory volumeMounts: - device: /dev/nvme1n1 path: /data
Defensive patterns
Strategy: validation
Validate before calling
// Before nodeup runs, on the node:
// test -e /data && [ ! -d /data ] && echo "CONFLICT: regular file at mount path"
os.Stat(path)
if err == nil && !info.IsDir() {
return fmt.Errorf("volumeMounts path %s exists and is not a directory", path)
}
// also check writability of parent: os.WriteFile(dir+"/.w", nil, 0600) Type guard
func isMountablePath(path string) error {
if fi, err := os.Stat(path); err == nil && !fi.IsDir() {
return fmt.Errorf("%s is a %v, not a directory", path, fi.Mode())
}
return nil
} Try / catch
if err := b.EnsureDirectory(x.Path); err != nil {
if errors.Is(err, os.ErrExist) || isReadOnlyFS(err) {
klog.Errorf("cannot create mount dir %s: %v — fix node filesystem and retry", x.Path, err)
}
return fmt.Errorf("failed to ensure the directory: %s, error: %w", x.Path, err)
} Prevention
- Verify volumeMounts paths don't collide with existing regular files on the root disk
- Ensure nodes have free disk space and a writable root filesystem before bootstrap
- Check SELinux/AppArmor policies allow creating the mount directories
- Run `kops get cluster -o yaml` review of volumeMounts entries before rolling updates
When it happens
Trigger: NodeupConfig.VolumeMounts contains an entry whose Path cannot be created: EnsureDirectory returns an error (mkdir failed due to EACCES, EROFS, ENOSPC, or an existing non-directory file at that path).
Common situations: VolumeMounts path colliding with an existing regular file on the root filesystem; root disk full or read-only (e.g. immutable/scratch node images); SELinux/AppArmor or restricted container runtime denying mkdir; mistyped mount path such as a path under a directory that only appears after another mount.
Related errors
- failed to check if device %q is mounted, error: %w
- path: %s already exists but is not a directory
- failed to read %s: %w
- failed to create bpf mount unit: %w
- failed to create cgroupv2 mount unit: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1b60092ec590b4a6.
Report an issue: GitHub.