{"record":{"id":"1b60092ec590b4a6","repo":"kubernetes/kops","slug":"failed-to-ensure-the-directory-s-error-w","errorCode":null,"errorMessage":"failed to ensure the directory: %s, error: %w","messagePattern":"failed to ensure the directory: (.+?), error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodeup/pkg/model/volumes.go","lineNumber":49,"sourceCode":"\t*NodeupModelContext\n}\n\nvar _ fi.NodeupModelBuilder = &VolumesBuilder{}\n\n// Build is responsible for handling the mounting additional volumes onto the instance\nfunc (b *VolumesBuilder) Build(c *fi.NodeupModelBuilderContext) error {\n\t// @step: check if the instancegroup has any volumes to mount\n\tif !b.UseVolumeMounts() {\n\t\tklog.V(1).Info(\"Skipping the volume builder, no volumes defined for this instancegroup\")\n\n\t\treturn nil\n\t}\n\n\t// @step: iterate the volume mounts and attempt to mount the devices\n\tfor _, x := range b.NodeupConfig.VolumeMounts {\n\t\t// @check the directory exists, else create it\n\t\tif err := b.EnsureDirectory(x.Path); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to ensure the directory: %s, error: %w\", x.Path, err)\n\t\t}\n\n\t\tm := &mount.SafeFormatAndMount{\n\t\t\tExec:      utilexec.New(),\n\t\t\tInterface: mount.New(\"\"),\n\t\t}\n\n\t\t// @check if the device is already mounted\n\t\tif found, err := b.IsMounted(m, x.Device, x.Path); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to check if device %q is mounted, error: %w\", x.Device, err)\n\t\t} else if found {\n\t\t\tklog.V(3).Infof(\"Skipping device: %s, path: %s as already mounted\", x.Device, x.Path)\n\t\t\tcontinue\n\t\t}\n\n\t\tklog.Infof(\"Attempting to format and mount device: %s, path: %s\", x.Device, x.Path)\n\n\t\tif err := m.FormatAndMount(x.Device, x.Path, x.Filesystem, x.MountOptions); err != nil {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/nodeup/pkg/model/volumes.go#L31-L67","documentation":"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'.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: path is an existing regular file, mkdir fails\nvolumeMounts:\n- device: /dev/nvme1n1\n  path: /data/file.txt\n// after: point the mount at a directory\nvolumeMounts:\n- device: /dev/nvme1n1\n  path: /data","handlingStrategy":"validation","validationCode":"// Before nodeup runs, on the node:\n// test -e /data && [ ! -d /data ] && echo \"CONFLICT: regular file at mount path\"\nos.Stat(path)\nif err == nil && !info.IsDir() {\n\treturn fmt.Errorf(\"volumeMounts path %s exists and is not a directory\", path)\n}\n// also check writability of parent: os.WriteFile(dir+\"/.w\", nil, 0600)","typeGuard":"func isMountablePath(path string) error {\n\tif fi, err := os.Stat(path); err == nil && !fi.IsDir() {\n\t\treturn fmt.Errorf(\"%s is a %v, not a directory\", path, fi.Mode())\n\t}\n\treturn nil\n}","tryCatchPattern":"if err := b.EnsureDirectory(x.Path); err != nil {\n\tif errors.Is(err, os.ErrExist) || isReadOnlyFS(err) {\n\t\tklog.Errorf(\"cannot create mount dir %s: %v — fix node filesystem and retry\", x.Path, err)\n\t}\n\treturn fmt.Errorf(\"failed to ensure the directory: %s, error: %w\", x.Path, err)\n}","preventionTips":["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"],"tags":["volumes","mount","filesystem","nodeup"],"backgroundTag":"directory-creation-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}