kubernetes/kops · error

error deleting loadbalancer: %v

Error message

error deleting loadbalancer: %v

What it means

Inside deleteLB, loadbalancers.Delete (with DeleteOpts such as cascade) is executed under vfs.RetryWithBackoff; non-NotFound failures are wrapped as 'error deleting loadbalancer: %v'. It indicates the Octavia API rejected or failed the LB deletion after retries, with the underlying reason preserved in %v.

Source

Thrown at upup/pkg/fi/cloudup/openstack/loadbalancer.go:192

		return nil
	} else {
		return wait.ErrWaitTimeout
	}
}

func (c *openstackCloud) DeleteLB(lbID string, opts loadbalancers.DeleteOpts) error {
	return deleteLB(c, lbID, opts)
}

func deleteLB(c OpenstackCloud, lbID string, opts loadbalancers.DeleteOpts) error {
	if c.LoadBalancerClient() == nil {
		return fmt.Errorf("loadbalancer support not available in this deployment")
	}

	done, err := vfs.RetryWithBackoff(deleteBackoff, func() (bool, error) {
		err := loadbalancers.Delete(context.TODO(), c.LoadBalancerClient(), lbID, opts).ExtractErr()
		if err != nil && !isNotFound(err) {
			return false, fmt.Errorf("error deleting loadbalancer: %v", err)
		}
		if isNotFound(err) {
			return true, nil
		}
		return false, nil
	})
	if err != nil {
		return err
	} else if done {
		return nil
	} else {
		return wait.ErrWaitTimeout
	}
}

func (c *openstackCloud) CreateLB(opt loadbalancers.CreateOptsBuilder) (*loadbalancers.LoadBalancer, error) {
	return createLB(c, opt)
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Retry after the LB leaves PENDING_* state — the helper already backs off; a persistent 409 means stuck resources
  2. Fix amphora/VM state (force-delete or reset via Octavia CLI) if the LB is in ERROR
  3. Verify DeleteOpts match the deployed Octavia version (cascade support) and adjust accordingly
  4. Check RBAC/quota for the service project, then retry
  5. Manually delete the LB resource with openstack loadbalancer delete --cascade to unblock teardown
Defensive patterns

Strategy: retry

Validate before calling

lb, err := cloud.GetLB(lbID, loadbalancers.GetOpts{})
if err != nil && isNotFound(err) { return nil } // nothing to delete
if err != nil { return err }
if strings.HasPrefix(lb.ProvisioningStatus, "PENDING") {
	return fmt.Errorf("loadbalancer %s is %s; wait before deleting", lbID, lb.ProvisioningStatus)
}

Try / catch

done, err := vfs.RetryWithBackoff(deleteBackoff, func() (bool, error) {
	err := loadbalancers.Delete(context.TODO(), client, lbID, opts).ExtractErr()
	if isNotFound(err) { return true, nil }
	if err != nil {
		var gerr gophercloud.ErrUnexpectedResponseCode
		if errors.As(err, &gerr) && gerr.Actual == 409 {
			return false, nil // PENDING state: keep retrying
		}
		return false, fmt.Errorf("error deleting loadbalancer: %v", err)
	}
	return true, nil
})

Prevention

When it happens

Trigger: Deleting an LB stuck in PENDING_UPDATE/PENDING_DELETE (409), insufficient quotas or RBAC (403), cascade delete unsupported by the deployed Octavia version, or transient 5xx/timeouts.

Common situations: Octavia amphora in ERROR state preventing deletion; concurrent reconciliation deleting the same LB; older Octavia releases lacking cascade cascade=true semantics passed via DeleteOpts; neutron quota exhaustion.

Related errors


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