{"record":{"id":"54994f205f98fb27","repo":"kubernetes/kops","slug":"expected-v1-pod-object-in-manifest-s-found-t","errorCode":null,"errorMessage":"expected v1.Pod object in manifest %s, found %T","messagePattern":"expected v1\\.Pod object in manifest (.+?), found %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/components/etcdmanager/model.go","lineNumber":264,"sourceCode":"\tvar pod *v1.Pod\n\tvar container *v1.Container\n\n\tvar manifest []byte\n\n\t// TODO: pull from bundle\n\tbundle := \"(embedded etcd manifest)\"\n\tmanifest = []byte(defaultManifest)\n\n\t{\n\t\tobjects, err := model.ParseManifest(manifest)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(objects) != 1 {\n\t\t\treturn nil, fmt.Errorf(\"expected exactly one object in manifest %s, found %d\", bundle, len(objects))\n\t\t}\n\t\tif podObject, ok := objects[0].(*v1.Pod); !ok {\n\t\t\treturn nil, fmt.Errorf(\"expected v1.Pod object in manifest %s, found %T\", bundle, objects[0])\n\t\t} else {\n\t\t\tpod = podObject\n\t\t}\n\t}\n\n\tetcdVersions := etcdSupportedVersions()\n\tif etcdCluster.Image != \"\" {\n\t\t// With a custom image, only the selected version's binaries are made\n\t\t// available in the pod; restoring backups, which can require the\n\t\t// binaries of a bundled version, is not supported.\n\t\tetcdVersions = []etcdVersion{{Version: strings.TrimPrefix(etcdCluster.Version, \"v\"), Image: etcdCluster.Image}}\n\t}\n\n\tfor _, etcdVersion := range etcdVersions {\n\t\tif etcdVersion.SymlinkToVersion == \"\" {\n\t\t\tvolume := v1.Volume{\n\t\t\t\tName: \"etcd-v\" + strings.ReplaceAll(etcdVersion.Version, \".\", \"-\"),\n\t\t\t\tVolumeSource: v1.VolumeSource{","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/components/etcdmanager/model.go#L246-L282","documentation":"After confirming exactly one object in the manifest bundle, buildPod type-asserts it to *v1.Pod. If the single object is another kind (Deployment, StatefulSet, etc.), the assertion fails and this error reports the actual Go type via %T.","triggerScenarios":"buildManifest -> buildPod with a bundle whose single document is a non-Pod kind, e.g. users substituting their own etcd-manager Deployment YAML for the expected Pod template.","commonSituations":"Swapping the etcd-manager manifest for a Deployment/StatefulSet copied from another cluster; template drift after upstream changed the expected kind.","solutions":["Convert the object to a bare Pod spec (kind: Pod) with the same containers/volumes.","Use the stock etcd-manager Pod manifest as the base and apply only image/flag changes.","If overriding via etcdCluster.Manager.image, keep the original manifest and only set the image instead of replacing the manifest."],"exampleFix":"// before\napiVersion: apps/v1\nkind: Deployment\nmetadata: {name: etcd-manager}\n// after\napiVersion: v1\nkind: Pod\nmetadata: {name: etcd-manager}","handlingStrategy":"type-guard","validationCode":"objs, _ := model.ParseManifest(bundle)\nif len(objs) == 1 {\n\tif _, ok := objs[0].(*v1.Pod); !ok {\n\t\treturn fmt.Errorf(\"bundle %s must contain a v1.Pod, got %T\", bundle, objs[0])\n\t}\n}","typeGuard":"func isPod(o runtime.Object) (*v1.Pod, bool) {\n\tp, ok := o.(*v1.Pod)\n\treturn p, ok\n}","tryCatchPattern":null,"preventionTips":["Base custom etcd-manager manifests on the stock Pod template, not on Deployments/StatefulSets.","Override only the image via etcdCluster.Manager.image instead of replacing the manifest kind."],"tags":["kops","etcd-manager","manifest","type-mismatch"],"backgroundTag":"manifest-wrong-resource-kind","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"}