{"record":{"id":"28157eee8bb80716","repo":"kubernetes/kops","slug":"unexpected-object-type-for-cluster-q-t","errorCode":null,"errorMessage":"unexpected object type for Cluster %q: %T","messagePattern":"unexpected object type for Cluster %q: %T","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/get_cluster.go","lineNumber":302,"sourceCode":"\tfor _, cluster := range clusters {\n\t\tconfigBase, err := registry.ConfigBase(vfsContext, cluster)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading full cluster spec for %q: %v\", cluster.ObjectMeta.Name, err)\n\t\t}\n\t\tconfigPath := configBase.Join(registry.PathClusterCompleted)\n\t\tb, err := configPath.ReadFile(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error loading Cluster %q: %v\", configPath, err)\n\t\t}\n\n\t\to, _, err := kopscodecs.Decode(b, nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing Cluster %q: %v\", configPath, err)\n\t\t}\n\t\tif fullSpec, ok := o.(*kopsapi.Cluster); ok {\n\t\t\tfullSpecs = append(fullSpecs, fullSpec)\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"unexpected object type for Cluster %q: %T\", configPath, o)\n\t\t}\n\t}\n\treturn fullSpecs, nil\n}\n","sourceCodeStart":284,"sourceCodeEnd":307,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/get_cluster.go#L284-L307","documentation":"After successful decoding, fullClusterSpecs asserts the decoded object is a *kopsapi.Cluster. If the codec returned a different runtime.Object type (e.g. an InstanceGroup or a different registered kind stored at that path), it returns 'unexpected object type for Cluster %q: %T'. This guards against state-store content placed at the wrong key.","triggerScenarios":"`kops get cluster X --full` where the object at <configBase>/cluster-completed.spec decodes to a non-Cluster kops object — typically because someone wrote an unrelated manifest (e.g. instancegroup spec) to that path, or a kops version stored a different type there.","commonSituations":"Manual state-store surgery (copying files between cluster prefixes); custom tooling writing specs; kops version drift changing the stored object kind.","solutions":["Inspect the object at the config path (`aws s3 cp`/`gsutil cat`) and check its `kind:` field — it must be `Cluster`.","Restore the correct cluster-completed.spec from backup or regenerate it with `kops update cluster <name>`.","Verify the state store prefix isn't mixing files from multiple clusters.","Use a matching kops binary version for the cluster's creation version."],"exampleFix":"// before\n# kind: InstanceGroup stored at cluster-completed.spec\n// after\n# restore correct spec\naws s3 cp correct-cluster-completed.spec s3://bucket/mycluster.example.com/cluster-completed.spec","handlingStrategy":"type-guard","validationCode":"# confirm the object at the config path is kind: Cluster\naws s3 cp \"s3://bucket/mycluster.example.com/cluster-completed.spec\" - | head -5 | grep -q '^kind: Cluster$' \\\n  || { echo \"wrong object kind at cluster-completed.spec\" >&2; exit 1; }","typeGuard":"null","tryCatchPattern":"if ! kops get cluster \"$CLUSTER\" --full 2>err.txt; then\n  grep -q 'unexpected object type' err.txt && \\\n    echo \"object at cluster-completed.spec is not a Cluster manifest; restore or regenerate via kops update\"\nfi","preventionTips":["Never place non-Cluster manifests at the cluster-completed.spec key.","Avoid copying files between cluster prefixes in the state store.","Use a kops binary version consistent with how the cluster state was written."],"tags":["type-mismatch","cluster-spec","state-store"],"backgroundTag":"unexpected-object-type","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"}