{"record":{"id":"b12f96fb72095a6f","repo":"kubernetes/kops","slug":"path-s-already-exists-but-is-not-a-directory","errorCode":null,"errorMessage":"path: %s already exists but is not a directory","messagePattern":"path: (.+?) already exists but is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodeup/pkg/model/context.go","lineNumber":173,"sourceCode":"\t\tname += \".service\"\n\t}\n\n\treturn name\n}\n\n// EnsureDirectory ensures the directory exists or creates it\nfunc (c *NodeupModelContext) EnsureDirectory(path string) error {\n\tst, err := os.Stat(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn os.MkdirAll(path, 0o755)\n\t\t}\n\n\t\treturn err\n\t}\n\n\tif !st.IsDir() {\n\t\treturn fmt.Errorf(\"path: %s already exists but is not a directory\", path)\n\t}\n\n\treturn nil\n}\n\n// IsMounted checks if the device is mount\nfunc (c *NodeupModelContext) IsMounted(m mount.Interface, device, path string) (bool, error) {\n\tlist, err := m.List()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tfor _, x := range list {\n\t\tif x.Device == device {\n\t\t\tklog.V(3).Infof(\"Found mountpoint device: %s, path: %s, type: %s\", x.Device, x.Path, x.Type)\n\t\t\tif strings.TrimSuffix(x.Path, \"/\") == strings.TrimSuffix(path, \"/\") {\n\t\t\t\treturn true, nil\n\t\t\t}","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/nodeup/pkg/model/context.go#L155-L191","documentation":"NodeupModelContext.EnsureDirectory (nodeup/pkg/model/context.go:173) creates a directory with os.MkdirAll if missing, and otherwise verifies the existing path is a directory via os.Stat. This error means the path already exists on the node filesystem but is a regular file, symlink-to-file, socket, etc. — not a directory — so nodeup cannot use it as a directory. It is a filesystem state conflict, not a permission problem.","triggerScenarios":"Any Build step that calls EnsureDirectory(path) where os.Stat(path) succeeds, IsNotExist is false, and st.IsDir() is false — i.e. a file occupies a path nodeup expects to be a directory (e.g. /var/log/kops, mounts dirs, /etc/kubernetes manifests directories).","commonSituations":"A previous failed bootstrap left a regular file where a directory belongs; container/image builds or custom base images placed a file at a kops-managed path; a volume mount incorrectly mounted a file at a directory path; manual experimentation on the node created stray files.","solutions":["SSH to the node and inspect the path: ls -la <path> to confirm it is a file","Move the offending file aside (mv <path> <path>.bak) and re-run nodeup so MkdirAll creates the directory","If the file is from a bad volume mount or image layer, fix the mount/image definition rather than just deleting the file","After remediation, confirm the directory exists with correct 0755 permissions and restart the nodeup/bootstrap process"],"exampleFix":"# before: a file blocks the expected directory\n$ ls -la /var/log/kops\n-rw-r--r-- 1 root root 0 ... /var/log/kops\n# after\n$ mv /var/log/kops /var/log/kops.bak && mkdir -p /var/log/kops","handlingStrategy":"try-catch","validationCode":"// Pre-check on the node before bootstrapping:\nst, err := os.Stat(path)\nif err == nil && !st.IsDir() {\n    return fmt.Errorf(\"%s must be a directory; move it aside first\", path)\n}","typeGuard":null,"tryCatchPattern":"if err := ctx.EnsureDirectory(path); err != nil {\n    if strings.Contains(err.Error(), \"already exists but is not a directory\") {\n        // remediate: mv the file aside, then retry EnsureDirectory\n        os.Rename(path, path+\".bak\")\n        return ctx.EnsureDirectory(path)\n    }\n    return err\n}","preventionTips":["Inspect node filesystem state (base image, volume mounts) for files colliding with kops-managed paths","Verify volume mounts target directory paths, not file paths","After failed bootstraps, check for stray files before retrying","Keep kops-managed directories (e.g. /var/log/kops, /etc/kubernetes) out of custom image build scripts"],"tags":["filesystem","nodeup","directory"],"backgroundTag":"path-is-not-a-directory","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"}