kubernetes/kops · error

unexpected kind for cluster, got %T, want kops.Cluster

Error message

unexpected kind for cluster, got %T, want kops.Cluster

What it means

GetCluster performs a VFS-based read of the cluster object and then asserts the returned untyped object is a *kops.Cluster. When the parsed object stored at that path is of a different Go type, the type assertion fails and this error is returned instead of panicking. It protects callers from silently using the wrong object kind as a cluster.

Source

Thrown at cmd/kops-controller/pkg/controllerclientset/clientset.go:75

	if name != c.clusterName {
		return nil, fmt.Errorf("clientset bound to cluster %q, got cluster %q", c.clusterName, name)
	}

	p := c.clusterBasePath.Join("config")
	b, err := p.ReadFile(ctx)
	if err != nil {
		return nil, fmt.Errorf("reading file %v: %w", p, err)
	}

	gvk := kops.SchemeGroupVersion.WithKind("Cluster")
	object, _, err := kopscodecs.Decode(b, &gvk)
	if err != nil {
		return nil, fmt.Errorf("error parsing %v: %w", p, err)
	}

	cluster, ok := object.(*kops.Cluster)
	if !ok {
		return nil, fmt.Errorf("unexpected kind for cluster, got %T, want kops.Cluster", object)
	}
	return cluster, nil
}

// VFSContext returns a VFSContext.
func (c *client) VFSContext() *vfs.VFSContext {
	return c.vfsContext
}

// CreateCluster creates a cluster
func (c *client) CreateCluster(ctx context.Context, cluster *kops.Cluster) (*kops.Cluster, error) {
	return nil, fmt.Errorf("method CreateCluster not supported in server-side client")
}

// UpdateCluster updates a cluster
func (c *client) UpdateCluster(ctx context.Context, cluster *kops.Cluster, status *kops.ClusterStatus) (*kops.Cluster, error) {
	return nil, fmt.Errorf("method UpdateCluster not supported in server-side client")
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the state store path passed (via --state or KOPS_STATE_STORE) points at the cluster registry root containing a Cluster object, not an instancegroup or other file
  2. Inspect the object at the path (kops get cluster -o yaml or read the VFS file) and confirm its kind is Cluster
  3. Re-create or repair the cluster state with `kops replace -f cluster.yaml` / `kops create cluster` if the file is corrupted or of the wrong kind
  4. Upgrade/align the kops CLI version with the one that wrote the state store to avoid legacy object kinds

Example fix

// before: parsing whatever file the path points at and asserting blindly
cluster, ok := object.(*kops.Cluster)
if !ok {
  return nil, fmt.Errorf("unexpected kind for cluster, got %T, want kops.Cluster", object)
}
// after (caller side): resolve the correct cluster path first
clusterPath := configBase.Join("cluster", kops.ModelID) // or use clientset GetCluster, not raw VFS reads
cluster, err := clientset.GetCluster(ctx, clusterPath)
Defensive patterns

Strategy: type-guard

Validate before calling

obj, err := vfsContext.ReadFile(p)
if err != nil { return err }
if !bytes.Contains(obj, []byte("kind: Cluster")) {
  return fmt.Errorf("path %s does not contain a Cluster object", p)
}

Type guard

func asCluster(object runtime.Object) (*kops.Cluster, error) {
  c, ok := object.(*kops.Cluster)
  if !ok {
    return nil, fmt.Errorf("unexpected kind for cluster, got %T", object)
  }
  return c, nil
}

Try / catch

cluster, err := clientset.GetCluster(ctx, p)
if err != nil {
  if strings.Contains(err.Error(), "unexpected kind for cluster") {
    // wrong object kind at path: verify state store path / repair state
  }
  return err
}

Prevention

When it happens

Trigger: The VFS path `p` contains a serialized k8s API object that is not a kops.Cluster (e.g. an InstanceGroup, a ClusterStatus, or a corrupted/legacy file), so object.(*kops.Cluster) fails after successful parsing.

Common situations: Pointing kops at a wrong or stale config path (e.g. an instancegroup file or old state layout); state-store contents written by a different kops version; manual edits or copy mistakes in the state store bucket.

Related errors


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