{"record":{"id":"60e2a8a0044e8b32","repo":"kubernetes/kops","slug":"unexpected-kind-for-cluster-got-t-want-kops-clu","errorCode":null,"errorMessage":"unexpected kind for cluster, got %T, want kops.Cluster","messagePattern":"unexpected kind for cluster, got %T, want kops\\.Cluster","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops-controller/pkg/controllerclientset/clientset.go","lineNumber":75,"sourceCode":"\tif name != c.clusterName {\n\t\treturn nil, fmt.Errorf(\"clientset bound to cluster %q, got cluster %q\", c.clusterName, name)\n\t}\n\n\tp := c.clusterBasePath.Join(\"config\")\n\tb, err := p.ReadFile(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading file %v: %w\", p, err)\n\t}\n\n\tgvk := kops.SchemeGroupVersion.WithKind(\"Cluster\")\n\tobject, _, err := kopscodecs.Decode(b, &gvk)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing %v: %w\", p, err)\n\t}\n\n\tcluster, ok := object.(*kops.Cluster)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unexpected kind for cluster, got %T, want kops.Cluster\", object)\n\t}\n\treturn cluster, nil\n}\n\n// VFSContext returns a VFSContext.\nfunc (c *client) VFSContext() *vfs.VFSContext {\n\treturn c.vfsContext\n}\n\n// CreateCluster creates a cluster\nfunc (c *client) CreateCluster(ctx context.Context, cluster *kops.Cluster) (*kops.Cluster, error) {\n\treturn nil, fmt.Errorf(\"method CreateCluster not supported in server-side client\")\n}\n\n// UpdateCluster updates a cluster\nfunc (c *client) UpdateCluster(ctx context.Context, cluster *kops.Cluster, status *kops.ClusterStatus) (*kops.Cluster, error) {\n\treturn nil, fmt.Errorf(\"method UpdateCluster not supported in server-side client\")\n}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops-controller/pkg/controllerclientset/clientset.go#L57-L93","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Inspect the object at the path (kops get cluster -o yaml or read the VFS file) and confirm its kind is Cluster","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","Upgrade/align the kops CLI version with the one that wrote the state store to avoid legacy object kinds"],"exampleFix":"// before: parsing whatever file the path points at and asserting blindly\ncluster, ok := object.(*kops.Cluster)\nif !ok {\n  return nil, fmt.Errorf(\"unexpected kind for cluster, got %T, want kops.Cluster\", object)\n}\n// after (caller side): resolve the correct cluster path first\nclusterPath := configBase.Join(\"cluster\", kops.ModelID) // or use clientset GetCluster, not raw VFS reads\ncluster, err := clientset.GetCluster(ctx, clusterPath)","handlingStrategy":"type-guard","validationCode":"obj, err := vfsContext.ReadFile(p)\nif err != nil { return err }\nif !bytes.Contains(obj, []byte(\"kind: Cluster\")) {\n  return fmt.Errorf(\"path %s does not contain a Cluster object\", p)\n}","typeGuard":"func asCluster(object runtime.Object) (*kops.Cluster, error) {\n  c, ok := object.(*kops.Cluster)\n  if !ok {\n    return nil, fmt.Errorf(\"unexpected kind for cluster, got %T\", object)\n  }\n  return c, nil\n}","tryCatchPattern":"cluster, err := clientset.GetCluster(ctx, p)\nif err != nil {\n  if strings.Contains(err.Error(), \"unexpected kind for cluster\") {\n    // wrong object kind at path: verify state store path / repair state\n  }\n  return err\n}","preventionTips":["Always point KOPS_STATE_STORE / --state at the cluster registry root, not individual object files","Run `kops get cluster` to sanity-check the state store before programmatic access","Pin the same kops version for writes and reads of the state store"],"tags":["go","type-assertion","vfs","kops"],"backgroundTag":"wrong-object-kind-in-state-store","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}