{"record":{"id":"0ddbeaff9edbeb08","repo":"kubernetes/kops","slug":"spotinst-unexpected-instance-group-type-got-t","errorCode":null,"errorMessage":"spotinst: unexpected instance group type, got: %T","messagePattern":"spotinst: unexpected instance group type, got: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/spotinst/resources.go","lineNumber":165,"sourceCode":"\tcase InstanceGroup:\n\t\t{\n\t\t\tvar svc InstanceGroupService\n\t\t\tswitch obj.Type() {\n\t\t\tcase InstanceGroupElastigroup:\n\t\t\t\tsvc = cloud.Elastigroup()\n\t\t\tcase InstanceGroupOcean:\n\t\t\t\tsvc = cloud.Ocean()\n\t\t\t}\n\n\t\t\treturn svc.Delete(context.Background(), obj.Id())\n\t\t}\n\tcase LaunchSpec:\n\t\t{\n\t\t\treturn cloud.LaunchSpec().Delete(context.Background(), obj.Id())\n\t\t}\n\t}\n\n\treturn fmt.Errorf(\"spotinst: unexpected instance group type, got: %T\", group.Raw)\n}\n\n// DeleteInstance removes an instance from its instance group.\nfunc DeleteInstance(cloud Cloud, instance *cloudinstances.CloudInstance) error {\n\tklog.V(2).Infof(\"Detaching instance %q from instance group: %q\",\n\t\tinstance.ID, instance.CloudInstanceGroup.HumanName)\n\n\tgroup := instance.CloudInstanceGroup\n\tswitch obj := group.Raw.(type) {\n\tcase InstanceGroup:\n\t\t{\n\t\t\tvar svc InstanceGroupService\n\t\t\tswitch obj.Type() {\n\t\t\tcase InstanceGroupElastigroup:\n\t\t\t\tsvc = cloud.Elastigroup()\n\t\t\tcase InstanceGroupOcean:\n\t\t\t\tsvc = cloud.Ocean()\n\t\t\t}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/spotinst/resources.go#L147-L183","documentation":"DeleteInstanceGroup dispatches deletion based on the concrete Go type of the Spotinst group (Elastigroup vs LaunchSpec/Ocean). If group.Raw holds a type not covered by the type switch, deletion cannot proceed and this error reports the unexpected concrete type via %T. It indicates a new/unknown Spotinst group type or corrupted data.","triggerScenarios":"DeleteGroup → DeleteInstanceGroup (pkg/resources/spotinst/resources.go:165) receives a group whose Raw field is neither ElasticGroup nor LaunchSpec — e.g. a new Spotinst product (Ocean cluster type) added upstream but the kOps type switch not updated, or a mismatched SDK version returning a new struct.","commonSituations":"kOps and spotinst-sdk-go version drift after upgrade; cluster contains a mixture of Ocean and Elastigroup resources and the code path only handles the legacy types; manual state edits producing wrong Raw payloads.","solutions":["Upgrade kOps (and its spotinst-sdk-go dependency) to a version whose type switch covers your group type","Check which concrete type appears in the message (%T) and compare with the switch in DeleteInstanceGroup","Migrate the group to a supported type (Elastigroup or LaunchSpec) via the Spotinst console","Patch the type switch to handle the new group type and contribute the fix upstream"],"exampleFix":"// before\nswitch g := group.Raw.(type) {\ncase ElasticGroup: ...\ncase LaunchSpec: ...\n}\n// after — handle Ocean resources too\nswitch g := group.Raw.(type) {\ncase ElasticGroup: ...\ncase LaunchSpec: ...\ncase ocean.Cluster: return cloud.Ocean().DeleteCluster(context.Background(), g.Id())\n}","handlingStrategy":"type-guard","validationCode":"// Verify the group type is dispatchable before calling delete\nfunc isDeletableSpotinstGroup(group *spotinst.CloudInstanceGroup) bool {\n    switch group.Raw.(type) {\n    case spotinst.ElasticGroup, spotinst.LaunchSpec:\n        return true\n    }\n    return false\n}","typeGuard":"func knownSpotinstGroupType(raw interface{}) bool {\n    switch raw.(type) {\n    case spotinst.ElasticGroup, spotinst.LaunchSpec:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"if err := spotinst.DeleteInstanceGroup(cloud, group); err != nil {\n    if strings.Contains(err.Error(), \"unexpected instance group type\") {\n        klog.Errorf(\"unsupported spotinst group type; upgrade kOps or delete group %q manually\", group.HumanName)\n        return errUnsupportedGroup\n    }\n    return err\n}","preventionTips":["Match kOps and spotinst-sdk-go versions","Avoid mixing Ocean and legacy Elastigroup resources on old kOps builds","Check the %T output to identify unhandled types early","Test delete flows after SDK upgrades"],"tags":["spotinst","unsupported-type","delete","type-mismatch"],"backgroundTag":"unexpected-resource-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"}