kubernetes/kubernetes · critical

failed to walk through kubelet dropin directory %q: %w

Error message

failed to walk through kubelet dropin directory %q: %w

What it means

Emitted when filepath.WalkDir itself fails traversing --kubelet-drop-in-config-dir (server.go:382-383). This is a filesystem-level failure of the directory walk: the directory does not exist, is not a directory, or cannot be read due to permissions. It is distinct from per-file load errors, which surface as [380].

Source

Thrown at cmd/kubelet/app/server.go:383

		dropinConfigJSON, gvk, err := loadDropinConfigFileIntoJSON(path)
		if err != nil {
			return fmt.Errorf("failed to load kubelet dropin file, path: %s, error: %w", path, err)
		}
		if gvk == nil || gvk.Empty() {
			return fmt.Errorf("failed to load kubelet dropin file, path: %s, no apiVersion/kind", path)
		}
		// TODO: expand this once more than a single kubelet config version exists
		if *gvk != kubeletconfigv1beta1.SchemeGroupVersion.WithKind("KubeletConfiguration") {
			return fmt.Errorf("failed to load kubelet dropin file, path: %s, unknown apiVersion/kind: %v", path, gvk.String())
		}
		mergedConfigJSON, err := jsonpatch.MergePatch(baseKubeletConfigJSON, dropinConfigJSON)
		if err != nil {
			return fmt.Errorf("failed to merge drop-in and current config: %w", err)
		}
		baseKubeletConfigJSON = mergedConfigJSON
		return nil
	}); err != nil {
		return nil, fmt.Errorf("failed to walk through kubelet dropin directory %q: %w", kubeletDropInConfigDir, err)
	}

	// reset versioned config and decode
	versionedConfig = &kubeletconfigv1beta1.KubeletConfiguration{}
	if err := json.Unmarshal(baseKubeletConfigJSON, versionedConfig); err != nil {
		return nil, fmt.Errorf("failed to unmarshal merged JSON into kubelet configuration: %w", err)
	}
	// apply defaulting after decoding
	kubeletconfigv1beta1conversion.SetDefaults_KubeletConfiguration(versionedConfig)

	// convert back to internal config
	if err := kubeletconfigv1beta1conversion.Convert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration(versionedConfig, kubeletConfig, nil); err != nil {
		return nil, fmt.Errorf("failed to convert merged config to internal kubelet configuration: %w", err)
	}

	return skippedFiles, nil
}

View on GitHub (pinned to b882c60b40)

Solutions

  1. Confirm the directory exists and is a directory: `ls -ld <dir>`.
  2. Create it if missing: `sudo mkdir -p <dir>` (empty directory is valid — no drop-ins applied).
  3. Fix permissions/ownership so the kubelet user can read it, and check SELinux/AppArmor labels with `ls -Z <dir>`.
  4. Verify the path in the kubelet flags / systemd unit matches the on-disk path.
Defensive patterns

Strategy: validation

Validate before calling

// Verify the drop-in directory exists and is traversable before starting kubelet.
info, err := os.Stat(dropInDir)
if err != nil || !info.IsDir() {
    return fmt.Errorf("drop-in dir unusable: %w", err)
}

Prevention

When it happens

Trigger: The path passed via --kubelet-drop-in-config-dir does not exist (ENOENT), is a regular file rather than a directory, or the kubelet process lacks traverse/read permission on it. Produced at the WalkDir error return.

Common situations: Kubelet configured with a drop-in directory that was never created; path typo in the systemd unit; the directory lives on a mount that failed to mount at boot; SELinux label denies access.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/1b5e837f7854585b. Report an issue: GitHub.