{"record":{"id":"3b7c9fd6ea262f08","repo":"kubernetes/kops","slug":"clientset-bound-to-cluster-q-got-cluster-q","errorCode":null,"errorMessage":"clientset bound to cluster %q, got cluster %q","messagePattern":"clientset bound to cluster %q, got cluster %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops-controller/pkg/controllerclientset/clientset.go","lineNumber":58,"sourceCode":"\t\tclusterName:     clusterName,\n\n\t\tclusterKeystore:    clusterKeystore,\n\t\tclusterSecretStore: clusterSecretStore,\n\t}, nil\n}\n\ntype client struct {\n\tvfsContext         *vfs.VFSContext\n\tclusterBasePath    vfs.Path\n\tclusterName        string\n\tclusterKeystore    fi.CAStore\n\tclusterSecretStore fi.SecretStore\n}\n\n// GetCluster reads a cluster by name\nfunc (c *client) GetCluster(ctx context.Context, name string) (*kops.Cluster, error) {\n\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}","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops-controller/pkg/controllerclientset/clientset.go#L40-L76","documentation":"The controllerclientset client is bound to a single cluster (set at construction via c.clusterName); GetCluster rejects any requested name that differs. This is a strict name-mismatch guard so a misconfigured caller cannot silently read another cluster's config.","triggerScenarios":"Calling client.GetCluster(ctx, name) where name != c.clusterName — e.g. RunGetAll/RunGetClusters requesting multiple/other cluster names against a bound, single-cluster clientset.","commonSituations":"kops get operations iterating over several clusters while the controller clientset was created for one; stale CLI flag (--name) differing from the bound cluster; copy-pasted cluster name or typo.","solutions":["Use the exact bound cluster name (c.clusterName) in the request","Construct the clientset with the cluster you intend to query","Fix the --name/cluster flag passed to the calling command","Refactor to a multi-cluster clientset if cross-cluster reads are required"],"exampleFix":"// before\ncluster, err := clientset.GetCluster(ctx, \"prod.example.com\") // bound to dev.example.com\n// after\ncluster, err := clientset.GetCluster(ctx, \"dev.example.com\") // matches bound cluster","handlingStrategy":"validation","validationCode":"// before calling GetCluster\nif requestedName != boundClusterName {\n\treturn fmt.Errorf(\"refusing GetCluster(%q): clientset bound to %q\", requestedName, boundClusterName)\n}","typeGuard":"func (c *client) canServe(name string) bool {\n\treturn name == c.clusterName\n}","tryCatchPattern":"cluster, err := clientset.GetCluster(ctx, name)\nif err != nil {\n\tif strings.Contains(err.Error(), \"bound to cluster\") {\n\t\treturn fmt.Errorf(\"wrong clientset for cluster %q\", name)\n\t}\n\treturn err\n}","preventionTips":["Keep the --name flag consistent with the clientset's bound cluster","Use the multi-cluster kops CLI state store path for cross-cluster queries","Avoid iterating cluster lists against a single-cluster clientset"],"tags":["clientset","cluster-name","mismatch","validation"],"backgroundTag":"cluster-name-mismatch","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}