kubernetes/kops · error

expected Pod object in manifest %s, found %T

Error message

expected Pod object in manifest %s, found %T

What it means

After the single-object check, buildHealthcheckSidecar type-asserts the parsed object to *corev1.Pod. If the sole object in the sidecar bundle manifest is not a Pod (e.g. a Deployment or ConfigMap), the assertion fails and this error reports the actual Go type via %T. It protects the subsequent code that directly manipulates pod.Spec fields.

Source

Thrown at pkg/model/components/kubeapiserver/model.go:130

// buildHealthcheckSidecar builds the partial pod for the healthcheck sidecar.
// nodeup will merge it into the kube-apiserver pod.
func (b *KubeApiserverBuilder) buildHealthcheckSidecar() (*corev1.Pod, error) {
	// TODO: pull from bundle
	bundle := "(embedded kube-apiserver-healthcheck manifest)"
	manifest := []byte(fmt.Sprintf(defaultManifest, kopsversion.KopsVersionImageTag(), wellknownports.KubeAPIServerHealthCheck))

	var pod *corev1.Pod
	var container *corev1.Container
	{
		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].(*corev1.Pod); !ok {
			return nil, fmt.Errorf("expected Pod object in manifest %s, found %T", bundle, objects[0])
		} else {
			pod = podObject
		}

		if len(pod.Spec.Containers) != 1 {
			return nil, fmt.Errorf("expected exactly one container in etcd-manager Pod, found %d", len(pod.Spec.Containers))
		}
		container = &pod.Spec.Containers[0]
	}

	// Remap image via AssetBuilder
	container.Image = b.AssetBuilder.RemapImage(container.Image)

	return pod, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Restore the official sidecar bundle (kind: Pod) by using an unmodified official kOps build
  2. Change the bundle's YAML document kind to Pod if maintaining a custom bundle
  3. Check git history of the assets/bundle directory for accidental replacements
  4. Report upstream if official release reproduces

Example fix

// before (bundle manifest)
apiVersion: apps/v1
kind: Deployment
// after
apiVersion: v1
kind: Pod
Defensive patterns

Strategy: type-guard

Validate before calling

// Pre-check bundle kind before model build
objects, err := model.ParseManifest(bundleBytes)
if err != nil {
    return err
}
if len(objects) == 1 {
    if _, ok := objects[0].(*corev1.Pod); !ok {
        return fmt.Errorf("bundle must define a Pod, got %T", objects[0])
    }
}

Type guard

// Narrow the parsed manifest object to a Pod
func asPod(obj runtime.Object) (*corev1.Pod, bool) {
    p, ok := obj.(*corev1.Pod)
    return p, ok
}

Try / catch

if err := buildManifest(); err != nil {
    if strings.Contains(err.Error(), "expected Pod object in manifest") {
        return fmt.Errorf("sidecar bundle kind wrong — restore kind: Pod: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: kops update cluster with a healthcheck sidecar bundle whose single YAML document defines a non-Pod kind — due to an edited/corrupted embedded bundle or a kOps build packaging the wrong file.

Common situations: Custom kOps builds where the sidecar bundle was accidentally replaced, or assets regenerated with the wrong template kind.

Related errors


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