kubernetes/kops · error

waiting for load-balancer %s after deletion: %w

Error message

waiting for load-balancer %s after deletion: %w

What it means

Wrap-around error from DeleteLoadBalancer's post-deletion WaitForLb: after DeleteLB, the code waits for the LB to disappear and only treats a 404 (gone) as success. If the wait returns any non-404 error, deletion is reported as failed with this wrapped error. Note that if err is nil here (LB still exists), the same message is returned since !is404Error(nil) is true.

Source

Thrown at upup/pkg/fi/cloudup/scaleway/cloud.go:577

			return nil
		}
		return fmt.Errorf("waiting for load-balancer: %w", err)
	}
	err = s.lbAPI.DeleteLB(&lb.ZonedAPIDeleteLBRequest{
		Zone: s.zone,
		LBID: loadBalancer.ID,
	})
	if err != nil {
		return fmt.Errorf("deleting load-balancer %s: %w", loadBalancer.ID, err)
	}

	// We wait for the load-balancer to be deleted, then we detach its IPs
	_, err = s.lbAPI.WaitForLb(&lb.ZonedAPIWaitForLBRequest{
		LBID: loadBalancer.ID,
		Zone: s.zone,
	})
	if !is404Error(err) {
		return fmt.Errorf("waiting for load-balancer %s after deletion: %w", loadBalancer.ID, err)
	}
	for _, ip := range ipsToRelease {
		err := s.lbAPI.ReleaseIP(&lb.ZonedAPIReleaseIPRequest{
			Zone: s.zone,
			IPID: ip.ID,
		})
		if err != nil {
			return fmt.Errorf("deleting load-balancer IP: %w", err)
		}
	}
	return nil
}

func (s *scwCloudImplementation) DeleteServer(server *instance.Server) error {
	srv, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
		Zone:     s.zone,
		ServerID: server.ID,
	})

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the LB state in the console or `scw lb lb get <id> zone=<zone>` — if it's gone, re-running teardown will succeed (404 tolerated).
  2. Retry after backoff; stuck deleting LBs usually terminate within minutes.
  3. Ensure only one kops delete/teardown runs at a time to avoid racing waits.
  4. If the LB is stuck for hours, contact Scaleway support or check status page, then re-run deletion.

Example fix

// before
_, err = s.lbAPI.WaitForLb(&lb.ZonedAPIWaitForLBRequest{LBID: loadBalancer.ID, Zone: s.zone})
if !is404Error(err) {
  return fmt.Errorf("waiting for load-balancer %s after deletion: %w", loadBalancer.ID, err)
}
// after
_, err = s.lbAPI.WaitForLb(&lb.ZonedAPIWaitForLBRequest{LBID: loadBalancer.ID, Zone: s.zone})
if err != nil && !is404Error(err) {
  return fmt.Errorf("waiting for load-balancer %s after deletion: %w", loadBalancer.ID, err)
}
Defensive patterns

Strategy: retry

Try / catch

err := kopsDeleteCluster()
if err != nil && strings.Contains(err.Error(), "after deletion") {
  // LB may still be terminating; wait and verify, then re-run teardown
  time.Sleep(2 * time.Minute)
  return retry(err)
}

Prevention

When it happens

Trigger: WaitForLb after DeleteLB returns a non-404 error: LB stuck in deleting state, API outage/rate limit during the wait, wrong zone, or the LB actually still existing because DeleteLB silently failed upstream.

Common situations: Scaleway LB taking long to terminate under load; API incident between DeleteLB and the wait; teardown retried concurrently by two kops runs; zone/config drift so the wrong LB is polled.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/e98f347530d169ef. Report an issue: GitHub.