{"record":{"id":"f57d303c8e90741e","repo":"kubernetes/kops","slug":"spotinst-does-not-support-surging","errorCode":null,"errorMessage":"spotinst does not support surging","messagePattern":"spotinst does not support surging","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/spotinst/resources.go","lineNumber":198,"sourceCode":"\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.Detach(context.Background(), obj.Id(), []string{instance.ID})\n\t\t}\n\tcase LaunchSpec:\n\t\t{\n\t\t\treturn cloud.Ocean().Detach(context.Background(), obj.OceanId(), []string{instance.ID})\n\t\t}\n\t}\n\n\treturn fmt.Errorf(\"spotinst: unexpected instance group type, got: %T\", group.Raw)\n}\n\n// DetachInstance is not implemented yet. It needs to cause a cloud instance to no longer be counted against the group's size limits.\nfunc DetachInstance(cloud Cloud, instance *cloudinstances.CloudInstance) error {\n\treturn fmt.Errorf(\"spotinst does not support surging\")\n}\n\n// GetCloudGroups returns a list of InstanceGroups as CloudInstanceGroup objects.\nfunc GetCloudGroups(cloud Cloud, cluster *kops.Cluster, instanceGroups []*kops.InstanceGroup,\n\twarnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error,\n) {\n\tcloudInstanceGroups := make(map[string]*cloudinstances.CloudInstanceGroup)\n\tnodeMap := cloudinstances.GetNodeMap(nodes, cluster)\n\n\t// List all resources.\n\tresources, err := ListResources(cloud, cluster.Name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Build all cloud instance groups.\n\tfor _, resource := range resources {\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/spotinst/resources.go#L180-L216","documentation":"DetachInstance is intentionally unimplemented for Spotinst: surging (detaching an instance so it stops counting against the group size while a replacement starts) has no Spotinst equivalent wired up in kOps. Any caller requesting a detach gets this fixed error message. It is a deliberate capability gap, not a runtime fault.","triggerScenarios":"Any code path calling DetachInstance (pkg/resources/spotinst/resources.go:198) — typically rolling-update flows that surge capacity by detaching old nodes before terminating — when the cluster's instance groups are backed by Spotinst groups.","commonSituations":"`kops rolling-update cluster` with surge settings on a Spotinst-backed cluster; automation scripts that call DetachInstance generically across cloud providers; validating Spotinst support for drain-like operations.","solutions":["Use rolling update without surging on Spotinst clusters (default behavior replaces instances one at a time)","Detach/remove the instance directly via the Spotinst API or console as a workaround","Implement detach support in the Spotinst provider and contribute upstream","Switch the instance group to a non-Spotinst cloud group if surging is a hard requirement"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Feature-check surging support before requesting detach\nfunc detachSupported(cloud fi.Cloud) bool {\n    _, isSpotinst := cloud.(spotinst.Cloud)\n    return !isSpotinst // spotinst never supports surging\n}","typeGuard":null,"tryCatchPattern":"if err := spotinst.DetachInstance(cloud, instance); err != nil {\n    if strings.Contains(err.Error(), \"does not support surging\") {\n        klog.V(2).Info(\"spotinst surging unsupported; falling back to direct replacement\")\n        return spotinst.DeleteInstance(cloud, instance) // fallback path\n    }\n    return err\n}","preventionTips":["Never configure surge rolling updates for spotinst-backed groups","Branch on cloud provider before calling generic detach logic","Treat this as a permanent limitation until upstream support lands","Use Spotinst-native replacement flows instead of kOps surging"],"tags":["spotinst","unimplemented","detach","rolling-update"],"backgroundTag":"operation-not-supported","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"}