{"record":{"id":"e780f3e5b2a72cc4","repo":"kubernetes/kops","slug":"failed-to-parse-spec-template-spec-from-deployment-e780f3","errorCode":null,"errorMessage":"failed to parse spec.template.spec from Deployment: %v","messagePattern":"failed to parse spec\\.template\\.spec from Deployment: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/components/addonmanifests/remap.go","lineNumber":94,"sourceCode":"\t\tmanifest = remapped\n\t}\n\n\treturn manifest, nil\n}\n\nfunc addServiceAccountRole(context *model.KopsModelContext, objects kubemanifest.ObjectList, serviceAccounts map[types.NamespacedName]iam.Subject) error {\n\tif !context.UseServiceAccountExternalPermissions() {\n\t\treturn nil\n\t}\n\n\tfor _, object := range objects {\n\t\tif !hasPodSpecTemplate(object) {\n\t\t\tcontinue\n\t\t}\n\t\tpodSpec := &corev1.PodSpec{}\n\n\t\tif err := object.Reparse(podSpec, \"spec\", \"template\", \"spec\"); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse spec.template.spec from Deployment: %v\", err)\n\t\t}\n\t\tsa := types.NamespacedName{\n\t\t\tName:      podSpec.ServiceAccountName,\n\t\t\tNamespace: object.GetNamespace(),\n\t\t}\n\t\tsubject := serviceAccounts[sa]\n\t\tif subject == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := iam.AddServiceAccountRole(&context.IAMModelContext, podSpec, subject); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif err := object.Set(podSpec, \"spec\", \"template\", \"spec\"); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to set object: %w\", err)\n\t\t}\n","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/components/addonmanifests/remap.go#L76-L112","documentation":"In addServiceAccountRole, each apps/v1 Deployment/DaemonSet's spec.template.spec is reparsed into a corev1.PodSpec so the IAM service-account role can be injected. If the YAML at that path cannot be decoded into a PodSpec (missing/invalid fields, wrong types), the function returns this error with the decode reason.","triggerScenarios":"addServiceAccountRole iterating objects where object.Reparse(podSpec, \"spec\",\"template\",\"spec\") fails: pod template absent, wrong apiVersion/kind slipped past hasPodSpecTemplate is impossible — so realistically invalid or non-standard PodSpec content in an apps/v1 Deployment/DaemonSet.","commonSituations":"Hand-edited addon manifests with type mismatches (e.g. containers as a string, resources mis-indented); manifests from a newer Kubernetes API with fields the vendored corev1 types reject (strict decoding); YAML indentation errors.","solutions":["Fix the PodSpec YAML at spec.template.spec so it is a valid corev1.PodSpec","Restore the stock addon manifest for the kops version in use","Remove non-standard/unknown fields from the pod template","Validate the manifest with kubectl apply --dry-run=server before feeding it to kops"],"exampleFix":"# before (type error: containers not a list)\nspec:\n  template:\n    spec:\n      containers: dns-controller\n# after\nspec:\n  template:\n    spec:\n      containers:\n        - name: dns-controller\n          image: ...","handlingStrategy":"validation","validationCode":"// Validate the pod template decodes cleanly before calling kops:\nvar podSpec corev1.PodSpec\nif err := yaml.UnmarshalStrict(templateBytes, &podSpec); err != nil {\n    return fmt.Errorf(\"spec.template.spec is not a valid PodSpec: %v\", err)\n}","typeGuard":"func hasValidPodTemplate(obj *kubemanifest.Object) bool {\n    var podSpec corev1.PodSpec\n    return hasPodSpecTemplate(obj) && obj.Reparse(&podSpec, \"spec\", \"template\", \"spec\") == nil\n}","tryCatchPattern":"if err := addServiceAccountRole(ctx, objects, sas); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse spec.template.spec\") {\n        return fmt.Errorf(\"manifest pod template invalid; restore stock manifest: %w\", err)\n    }\n    return err\n}","preventionTips":["Run kubectl apply --dry-run=server on custom manifests before kops consumes them","Avoid unknown/non-standard fields in pod templates","Keep addon manifests in sync with the kops release channel"],"tags":["kops","podspec","manifest-parsing","addon"],"backgroundTag":"podspec-parse-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}