{"record":{"id":"505d1735f2249f4f","repo":"kubernetes/kops","slug":"waiting-for-load-balancer-w","errorCode":null,"errorMessage":"waiting for load-balancer: %w","messagePattern":"waiting for load-balancer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/scaleway/cloud.go","lineNumber":561,"sourceCode":"\t\treturn fmt.Errorf(\"failed to delete record %s: %w\", record.Name, err)\n\t}\n\treturn nil\n}\n\nfunc (s *scwCloudImplementation) DeleteLoadBalancer(loadBalancer *lb.LB) error {\n\tipsToRelease := loadBalancer.IP\n\n\t// We delete the load-balancer once it's in a stable state\n\t_, err := s.lbAPI.WaitForLb(&lb.ZonedAPIWaitForLBRequest{\n\t\tLBID: loadBalancer.ID,\n\t\tZone: s.zone,\n\t})\n\tif err != nil {\n\t\tif is404Error(err) {\n\t\t\tklog.V(8).Infof(\"Load-balancer %q (%s) was already deleted\", loadBalancer.Name, loadBalancer.ID)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"waiting for load-balancer: %w\", err)\n\t}\n\terr = s.lbAPI.DeleteLB(&lb.ZonedAPIDeleteLBRequest{\n\t\tZone: s.zone,\n\t\tLBID: loadBalancer.ID,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"deleting load-balancer %s: %w\", loadBalancer.ID, err)\n\t}\n\n\t// We wait for the load-balancer to be deleted, then we detach its IPs\n\t_, err = s.lbAPI.WaitForLb(&lb.ZonedAPIWaitForLBRequest{\n\t\tLBID: loadBalancer.ID,\n\t\tZone: s.zone,\n\t})\n\tif !is404Error(err) {\n\t\treturn fmt.Errorf(\"waiting for load-balancer %s after deletion: %w\", loadBalancer.ID, err)\n\t}\n\tfor _, ip := range ipsToRelease {","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/scaleway/cloud.go#L543-L579","documentation":"Wrap-around error from DeleteLoadBalancer when the initial lb API WaitForLb call (used to confirm the LB exists/reads its state before deletion) fails for a non-404 reason. 404 is treated as already-deleted success; any other failure aborts deletion with this wrapped error.","triggerScenarios":"WaitForLb failure other than 404: wrong zone for the LB (LB lives in a different availability zone than s.zone), invalid LB ID, credentials/IAM permission problems, LB stuck in a transitional state, API outage or rate limit.","commonSituations":"Load balancer created in a zone different from the cluster's cloud zone after a config change; teardown run with credentials of a different project; Scaleway LB API incident during `kops delete cluster`.","solutions":["Verify the LB's actual zone and ID in the console or with `scw lb lb list`; ensure s.zone matches.","Confirm credentials/project can see the LB; reproduce with `scw lb lb get <id> zone=<zone>`.","Retry with backoff if the LB API returns 429/5xx or the LB is mid-transition; re-run teardown (404 is tolerated).","Check Scaleway status for LB API incidents."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// confirm LB zone/id before teardown\nlbs, err := lb.NewZonedAPI(client).ListLBs(&lb.ZonedAPIListLBsRequest{Zone: s.zone, Name: &lbName})\nif err != nil || lbs.TotalCount == 0 { /* LB not in this zone; skip or fix config */ }","typeGuard":null,"tryCatchPattern":"err := kopsDeleteCluster()\nvar scwErr *scw.Error\nif err != nil && errors.As(err, &scwErr) && (scwErr.StatusCode == 429 || scwErr.StatusCode >= 500) {\n  return retryWithBackoff(err)\n}","preventionTips":["Pin all cluster resources to the configured zone; avoid zone drift between LB and nodes.","Run teardown with the same credentials/project used for creation.","Retry idempotently: kops treats 404 as already-deleted, so re-running is safe."],"tags":["scaleway","load-balancer","deletion","api-error"],"backgroundTag":"load-balancer-deletion-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"}