{"record":{"id":"037fa10936b88c07","repo":"kubernetes/kops","slug":"timed-out-waiting-for-volume-to-detach","errorCode":null,"errorMessage":"timed out waiting for volume to detach","messagePattern":"timed out waiting for volume to detach","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/digitalocean/resources.go","lineNumber":335,"sourceCode":"func deleteLoadBalancer(cloud fi.Cloud, t *resources.Resource) error {\n\tc := cloud.(do.DOCloud)\n\tlb := t.Obj.(godo.LoadBalancer)\n\t_, err := c.LoadBalancersService().Delete(context.TODO(), lb.ID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete load balancer with name %s %v\", lb.Name, err)\n\t}\n\n\treturn nil\n}\n\nfunc waitForDetach(cloud do.DOCloud, action *godo.Action) error {\n\ttimeout := time.After(10 * time.Second)\n\tticker := time.NewTicker(500 * time.Millisecond)\n\tdefer ticker.Stop()\n\tfor {\n\t\tselect {\n\t\tcase <-timeout:\n\t\t\treturn errors.New(\"timed out waiting for volume to detach\")\n\t\tcase <-ticker.C:\n\t\t\tupdatedAction, _, err := cloud.ActionsService().Get(context.TODO(), action.ID)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif updatedAction.Status == godo.ActionCompleted {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc dumpDroplet(op *resources.DumpOperation, r *resources.Resource) error {\n\tdata := make(map[string]interface{})\n\tdata[\"id\"] = r.ID\n\tdata[\"type\"] = godo.DropletResourceType\n\tdata[\"raw\"] = r.Obj","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/digitalocean/resources.go#L317-L353","documentation":"Wraps a failure of ec2 DescribeLaunchTemplates inside findAutoscalingGroupLaunchTemplate. When the ASG specifies version \"\", \"$Default\", or \"$Latest\", kOps must resolve the actual version via DescribeLaunchTemplates; any SDK error is wrapped here (%q on the error prints it quoted).","triggerScenarios":"DescribeLaunchTemplates fails: launch template deleted while ASG still references it (returns InvalidLaunchTemplateId-type errors), missing ec2:DescribeLaunchTemplates permission, throttling, or region mismatch.","commonSituations":"Launch template manually deleted or Terraform-pruned; cross-account/cross-region template references; IAM policy missing ec2 describe permissions during rolling update.","solutions":["Re-create the deleted launch template or re-run `kops update cluster` to generate a new one attached to the ASG","Grant ec2:DescribeLaunchTemplates to the kOps IAM role","Verify the launch template exists in the same region/account: `aws ec2 describe-launch-templates --launch-template-ids <id>`","Retry on throttling errors"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"ltOut, err := cloud.EC2().DescribeLaunchTemplates(ctx, &ec2.DescribeLaunchTemplatesInput{LaunchTemplateIds: []string{ltID}})\nif err != nil || len(ltOut.LaunchTemplates) == 0 { return fmt.Errorf(\"launch template %q missing\", ltID) }","typeGuard":null,"tryCatchPattern":"err := rollingUpdate(ctx, cluster)\nvar invalidLT *ec2types.InvalidLaunchTemplateId\nif errors.As(err, &invalidLT) {\n  // launch template deleted: recreate via kops update cluster, then retry\n  recreateLaunchTemplates()\n} else if strings.Contains(err.Error(), \"error describing launch templates\") {\n  retryWithBackoff()\n}","preventionTips":["Never delete launch templates referenced by live ASGs (check references before Terraform destroy)","Grant ec2:DescribeLaunchTemplates in the IAM policy","Keep ASGs and templates in the same region/account","Run `aws ec2 describe-launch-templates --launch-template-ids <id>` to pre-validate"],"tags":["aws","ec2","launch-template","rolling-update"],"backgroundTag":"launch-template-resolution-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"}