kubernetes/kops · error

failed to build manifest path. Path was empty

Error message

failed to build manifest path. Path was empty

What it means

buildManifestDirectory creates the directory kubelet watches for static pods (spec.kubelet.podManifestPath). Since a static-pod manifest directory is mandatory for the kubelet setup nodeup performs, an empty PodManifestPath is treated as a hard configuration error rather than silently skipped.

Source

Thrown at nodeup/pkg/model/kubelet.go:458

// kubeletPath returns the path of the kubelet based on distro
func (b *KubeletBuilder) kubeletPath() string {
	return b.binaryPath() + "/kubelet"
}

// getECRCredentialProviderPath returns the path of the ECR Credentials Provider based on distro and archiecture
func (b *KubeletBuilder) getECRCredentialProviderPath() string {
	return b.binaryPath() + "/ecr-credential-provider"
}

// getGCPCredentialProviderPath returns the path of the GCP Credentials Provider based on distro and archiecture
func (b *KubeletBuilder) getGCPCredentialProviderPath() string {
	return b.binaryPath() + "/gcp-credential-provider"
}

// buildManifestDirectory creates the directory where kubelet expects static manifests to reside
func (b *KubeletBuilder) buildManifestDirectory(kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {
	if kubeletConfig.PodManifestPath == "" {
		return nil, fmt.Errorf("failed to build manifest path. Path was empty")
	}
	directory := &nodetasks.File{
		Path: kubeletConfig.PodManifestPath,
		Type: nodetasks.FileType_Directory,
		Mode: s("0755"),
	}
	return directory, nil
}

// buildSystemdEnvironmentFile renders the environment file for the kubelet
func (b *KubeletBuilder) buildSystemdEnvironmentFile(ctx context.Context, kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {
	// TODO: Dump the separate file for flags - just complexity!
	flags, err := flagbuilder.BuildFlags(kubeletConfig)
	if err != nil {
		return nil, fmt.Errorf("error building kubelet flags: %v", err)
	}

	if b.UsesSecondaryIP() {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set spec.kubelet.podManifestPath to a valid directory, e.g. /etc/kubernetes/manifests
  2. Do not set it to an empty string; omit the field entirely if defaults apply
  3. kops edit cluster, fix the value, then kops update cluster
  4. Check kops version-specific defaults if upgrading changed behavior

Example fix

// before
kubelet:
  podManifestPath: ""
// after
kubelet:
  podManifestPath: /etc/kubernetes/manifests
Defensive patterns

Strategy: validation

Validate before calling

if cluster.Spec.Kubelet != nil && cluster.Spec.Kubelet.PodManifestPath == "" {
    return errors.New("kubelet.podManifestPath must not be empty; use e.g. /etc/kubernetes/manifests")
}

Try / catch

dir, err := b.buildManifestDirectory(kubeletConfig)
if err != nil {
    return fmt.Errorf("set spec.kubelet.podManifestPath in the cluster spec: %w", err)
}

Prevention

When it happens

Trigger: buildManifestDirectory -> kubeletConfig.PodManifestPath == "", i.e. the cluster spec explicitly sets kubelet.podManifestPath to "" (Go zero value when cleared) while the KubeletBuilder.Build path still requires the directory.

Common situations: Users clearing podManifestPath in the cluster spec believing it disables static pods; config templates omitting the field where downstream code requires it; migrating specs between kops versions with different defaults.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/5785d41053b9cc95. Report an issue: GitHub.