kubernetes/kops · error
expected v1.Pod object in manifest %s, found %T
Error message
expected v1.Pod object in manifest %s, found %T
What it means
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.
Source
Thrown at pkg/model/components/etcdmanager/model.go:264
var pod *v1.Pod
var container *v1.Container
var manifest []byte
// TODO: pull from bundle
bundle := "(embedded etcd manifest)"
manifest = []byte(defaultManifest)
{
objects, err := model.ParseManifest(manifest)
if err != nil {
return nil, err
}
if len(objects) != 1 {
return nil, fmt.Errorf("expected exactly one object in manifest %s, found %d", bundle, len(objects))
}
if podObject, ok := objects[0].(*v1.Pod); !ok {
return nil, fmt.Errorf("expected v1.Pod object in manifest %s, found %T", bundle, objects[0])
} else {
pod = podObject
}
}
etcdVersions := etcdSupportedVersions()
if etcdCluster.Image != "" {
// With a custom image, only the selected version's binaries are made
// available in the pod; restoring backups, which can require the
// binaries of a bundled version, is not supported.
etcdVersions = []etcdVersion{{Version: strings.TrimPrefix(etcdCluster.Version, "v"), Image: etcdCluster.Image}}
}
for _, etcdVersion := range etcdVersions {
if etcdVersion.SymlinkToVersion == "" {
volume := v1.Volume{
Name: "etcd-v" + strings.ReplaceAll(etcdVersion.Version, ".", "-"),
VolumeSource: v1.VolumeSource{View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before
apiVersion: apps/v1
kind: Deployment
metadata: {name: etcd-manager}
// after
apiVersion: v1
kind: Pod
metadata: {name: etcd-manager} Defensive patterns
Strategy: type-guard
Validate before calling
objs, _ := model.ParseManifest(bundle)
if len(objs) == 1 {
if _, ok := objs[0].(*v1.Pod); !ok {
return fmt.Errorf("bundle %s must contain a v1.Pod, got %T", bundle, objs[0])
}
} Type guard
func isPod(o runtime.Object) (*v1.Pod, bool) {
p, ok := o.(*v1.Pod)
return p, ok
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Swapping the etcd-manager manifest for a Deployment/StatefulSet copied from another cluster; template drift after upstream changed the expected kind.
Related errors
- expected exactly one object in manifest %s, found %d
- expected exactly one container in etcd-manager Pod, found %d
- unhandled kind %q in %s
- must specify %q label with cluster name to replace SSHCreden
- spec.PublicKey is required
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/54994f205f98fb27.
Report an issue: GitHub.