kubernetes/kops · error
path: %s already exists but is not a directory
Error message
path: %s already exists but is not a directory
What it means
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.
Source
Thrown at nodeup/pkg/model/context.go:173
name += ".service"
}
return name
}
// EnsureDirectory ensures the directory exists or creates it
func (c *NodeupModelContext) EnsureDirectory(path string) error {
st, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return os.MkdirAll(path, 0o755)
}
return err
}
if !st.IsDir() {
return fmt.Errorf("path: %s already exists but is not a directory", path)
}
return nil
}
// IsMounted checks if the device is mount
func (c *NodeupModelContext) IsMounted(m mount.Interface, device, path string) (bool, error) {
list, err := m.List()
if err != nil {
return false, err
}
for _, x := range list {
if x.Device == device {
klog.V(3).Infof("Found mountpoint device: %s, path: %s, type: %s", x.Device, x.Path, x.Type)
if strings.TrimSuffix(x.Path, "/") == strings.TrimSuffix(path, "/") {
return true, nil
}View on GitHub (pinned to 4c8573c808)
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
Example fix
# before: a file blocks the expected directory $ ls -la /var/log/kops -rw-r--r-- 1 root root 0 ... /var/log/kops # after $ mv /var/log/kops /var/log/kops.bak && mkdir -p /var/log/kops
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check on the node before bootstrapping:
st, err := os.Stat(path)
if err == nil && !st.IsDir() {
return fmt.Errorf("%s must be a directory; move it aside first", path)
} Try / catch
if err := ctx.EnsureDirectory(path); err != nil {
if strings.Contains(err.Error(), "already exists but is not a directory") {
// remediate: mv the file aside, then retry EnsureDirectory
os.Rename(path, path+".bak")
return ctx.EnsureDirectory(path)
}
return err
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- failed to read %s: %w
- error checking for /run/cilium/cgroupv2: %v
- failed to ensure the directory: %s, error: %w
- error closing target: %w
- error creating temp dir: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/b12f96fb72095a6f.
Report an issue: GitHub.