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

  1. Convert the object to a bare Pod spec (kind: Pod) with the same containers/volumes.
  2. Use the stock etcd-manager Pod manifest as the base and apply only image/flag changes.
  3. 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

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


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