{"record":{"id":"efc277b2248014ff","repo":"kubernetes/kops","slug":"error-deleting-instance-q-node-q-v","errorCode":null,"errorMessage":"error deleting instance %q, node %q: %v","messagePattern":"error deleting instance %q, node %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/instancegroups/instancegroups.go","lineNumber":661,"sourceCode":"\treturn nil\n}\n\n// deleteInstance deletes an Cloud Instance.\nfunc (c *RollingUpdateCluster) deleteInstance(u *cloudinstances.CloudInstance) error {\n\tid := u.ID\n\tnodeName := \"\"\n\tif u.Node != nil {\n\t\tnodeName = u.Node.Name\n\t}\n\tif nodeName != \"\" {\n\t\tklog.Infof(\"Stopping instance %q, node %q, in group %q (this may take a while).\", id, nodeName, u.CloudInstanceGroup.HumanName)\n\t} else {\n\t\tklog.Infof(\"Stopping instance %q, in group %q (this may take a while).\", id, u.CloudInstanceGroup.HumanName)\n\t}\n\n\tif err := c.Cloud.DeleteInstance(u); err != nil {\n\t\tif nodeName != \"\" {\n\t\t\treturn fmt.Errorf(\"error deleting instance %q, node %q: %v\", id, nodeName, err)\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting instance %q: %v\", id, err)\n\t}\n\n\treturn nil\n}\n\n// drainNode drains a K8s node.\nfunc (c *RollingUpdateCluster) drainNode(ctx context.Context, u *cloudinstances.CloudInstance) error {\n\tif c.K8sClient == nil {\n\t\treturn fmt.Errorf(\"K8sClient not set\")\n\t}\n\n\tif u.Node == nil {\n\t\treturn fmt.Errorf(\"node not set\")\n\t}\n\n\tif u.Node.Name == \"\" {","sourceCodeStart":643,"sourceCodeEnd":679,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/instancegroups/instancegroups.go#L643-L679","documentation":"kOps deletes (terminates) the cloud instance after draining/detaching it. This error wraps a DeleteInstance failure from the cloud provider for an instance that has an associated node name, and aborts the rolling update for that instance.","triggerScenarios":"c.Cloud.DeleteInstance(u) errors while nodeName != \"\" — e.g. AWS TerminateInstanceInAutoScalingGroup rejected because the instance was already terminated or not in the ASG, IAM denial, or API throttling.","commonSituations":"Instance terminated concurrently by cluster-autoscaler or manually; spot instance reclaimed mid-roll; IAM missing terminate permission; API rate limits during large rolls.","solutions":["Re-run rolling update; it re-discovers actual group membership","Confirm IAM terminate-instance permissions","Check whether the instance was already terminated externally (cloud console)","Retry after cloud API throttling"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// check instance state before terminating\nout, _ := ec2Client.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{&u.ID}})\n// only terminate if state is running/pending and still a member of the ASG","typeGuard":"func terminable(u *cloudinstances.CloudInstance, state string) bool {\n    return u != nil && u.ID != \"\" && (state == \"running\" || state == \"pending\")\n}","tryCatchPattern":"if err := c.Cloud.DeleteInstance(u); err != nil {\n    if isNotFound(err) || isAlreadyTerminated(err) { return nil }\n    if isThrottling(err) { /* backoff and retry */ }\n    return fmt.Errorf(\"error deleting instance %q, node %q: %v\", id, nodeName, err)\n}","preventionTips":["Grant terminate IAM permissions (ec2:TerminateInstances, autoscaling:TerminateInstanceInAutoScalingGroup)","Pause cluster-autoscaler/scale-in policies during rolls","Handle spot-interruption risk by re-running rolls","Check cloud console for externally terminated instances before retrying"],"tags":["cloud","delete","rolling-update","instance"],"backgroundTag":"cloud-instance-delete-failed","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"}