{"record":{"id":"5785d41053b9cc95","repo":"kubernetes/kops","slug":"failed-to-build-manifest-path-path-was-empty","errorCode":null,"errorMessage":"failed to build manifest path. Path was empty","messagePattern":"failed to build manifest path\\. Path was empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodeup/pkg/model/kubelet.go","lineNumber":458,"sourceCode":"// kubeletPath returns the path of the kubelet based on distro\nfunc (b *KubeletBuilder) kubeletPath() string {\n\treturn b.binaryPath() + \"/kubelet\"\n}\n\n// getECRCredentialProviderPath returns the path of the ECR Credentials Provider based on distro and archiecture\nfunc (b *KubeletBuilder) getECRCredentialProviderPath() string {\n\treturn b.binaryPath() + \"/ecr-credential-provider\"\n}\n\n// getGCPCredentialProviderPath returns the path of the GCP Credentials Provider based on distro and archiecture\nfunc (b *KubeletBuilder) getGCPCredentialProviderPath() string {\n\treturn b.binaryPath() + \"/gcp-credential-provider\"\n}\n\n// buildManifestDirectory creates the directory where kubelet expects static manifests to reside\nfunc (b *KubeletBuilder) buildManifestDirectory(kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {\n\tif kubeletConfig.PodManifestPath == \"\" {\n\t\treturn nil, fmt.Errorf(\"failed to build manifest path. Path was empty\")\n\t}\n\tdirectory := &nodetasks.File{\n\t\tPath: kubeletConfig.PodManifestPath,\n\t\tType: nodetasks.FileType_Directory,\n\t\tMode: s(\"0755\"),\n\t}\n\treturn directory, nil\n}\n\n// buildSystemdEnvironmentFile renders the environment file for the kubelet\nfunc (b *KubeletBuilder) buildSystemdEnvironmentFile(ctx context.Context, kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {\n\t// TODO: Dump the separate file for flags - just complexity!\n\tflags, err := flagbuilder.BuildFlags(kubeletConfig)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error building kubelet flags: %v\", err)\n\t}\n\n\tif b.UsesSecondaryIP() {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/nodeup/pkg/model/kubelet.go#L440-L476","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set spec.kubelet.podManifestPath to a valid directory, e.g. /etc/kubernetes/manifests","Do not set it to an empty string; omit the field entirely if defaults apply","kops edit cluster, fix the value, then kops update cluster","Check kops version-specific defaults if upgrading changed behavior"],"exampleFix":"// before\nkubelet:\n  podManifestPath: \"\"\n// after\nkubelet:\n  podManifestPath: /etc/kubernetes/manifests","handlingStrategy":"validation","validationCode":"if cluster.Spec.Kubelet != nil && cluster.Spec.Kubelet.PodManifestPath == \"\" {\n    return errors.New(\"kubelet.podManifestPath must not be empty; use e.g. /etc/kubernetes/manifests\")\n}","typeGuard":null,"tryCatchPattern":"dir, err := b.buildManifestDirectory(kubeletConfig)\nif err != nil {\n    return fmt.Errorf(\"set spec.kubelet.podManifestPath in the cluster spec: %w\", err)\n}","preventionTips":["Never set podManifestPath to an empty string; omit the field to use defaults","Keep /etc/kubernetes/manifests as the standard path unless you have a reason","Add spec linting in CI to catch cleared required fields"],"tags":["kubelet","static-pods","config-validation"],"backgroundTag":"required-config-field-empty","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"}