kubernetes/kops · error

deleting virtual network: %w

Error message

deleting virtual network: %w

What it means

Wrapped when the initial BeginDelete call for a virtual network fails synchronously — the delete future was never created. ARM errors such as vnet not found, authorization failure, or invalid request are wrapped with %w. It is distinct from the later polling error ('waiting for virtual network deletion completion').

Source

Thrown at upup/pkg/fi/cloudup/azure/virtualnetwork.go:78

	pager := c.c.NewListPager(resourceGroupName, nil)
	for pager.More() {
		resp, err := pager.NextPage(ctx)
		if err != nil {
			var respErr *azcore.ResponseError
			if errors.As(err, &respErr) && respErr.ErrorCode == "ResourceGroupNotFound" {
				return nil, nil
			}
			return nil, fmt.Errorf("listing virtual networks: %w", err)
		}
		l = append(l, resp.Value...)
	}
	return l, nil
}

func (c *virtualNetworksClientImpl) Delete(ctx context.Context, resourceGroupName, vnetName string) error {
	future, err := c.c.BeginDelete(ctx, resourceGroupName, vnetName, nil)
	if err != nil {
		return fmt.Errorf("deleting virtual network: %w", err)
	}
	if _, err = future.PollUntilDone(ctx, nil); err != nil {
		return fmt.Errorf("waiting for virtual network deletion completion: %w", err)
	}
	return nil
}

func newVirtualNetworksClientImpl(subscriptionID string, cred *azidentity.DefaultAzureCredential) (*virtualNetworksClientImpl, error) {
	c, err := network.NewVirtualNetworksClient(subscriptionID, cred, nil)
	if err != nil {
		return nil, fmt.Errorf("creating virtual networks client: %w", err)
	}
	return &virtualNetworksClientImpl{
		c: c,
	}, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped azcore.ResponseError: 404 means the vnet is already gone and deletion can be treated as complete
  2. Grant the principal Contributor/Network Contributor on the resource group
  3. Verify resource group and vnet name match the cluster spec
  4. If dependent resources (e.g. load balancers, public IPs) block deletion, delete them first

Example fix

// before: hard failure on already-deleted vnet
if err := c.Delete(ctx, rg, vnet); err != nil { return err }
// after: treat 404 as success
if err := c.Delete(ctx, rg, vnet); err != nil {
    var respErr *azcore.ResponseError
    if !(errors.As(err, &respErr) && respErr.StatusCode == http.StatusNotFound) {
        return err
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: treat not-found vnet as already deleted before issuing delete
existing, err := vnetsClient.Get(ctx, rg, vnetName)
if err != nil && strings.Contains(err.Error(), "404") {
    return nil // nothing to delete
}

Type guard

func isNotFound(err error) bool {
    var respErr *azcore.ResponseError
    return errors.As(err, &respErr) && respErr.StatusCode == http.StatusNotFound
}

Try / catch

err := vnetsClient.Delete(ctx, rg, vnetName)
if err != nil {
    if isNotFound(err) {
        return nil // already gone
    }
    var respErr *azcore.ResponseError
    if errors.As(err, &respErr) && respErr.StatusCode == http.StatusForbidden {
        return fmt.Errorf("grant Contributor on %s to delete vnet: %w", rg, err)
    }
    return err
}

Prevention

When it happens

Trigger: virtualNetworksClientImpl.Delete calls c.c.BeginDelete(ctx, resourceGroupName, vnetName, nil) and the SDK immediately errors: vnet name/resource group mismatch, missing Microsoft.Network/virtualNetworks/delete permission, dependent resources blocking (for some errors surfaced at begin), or network failure.

Common situations: kops delete cluster against a cluster whose vnet was already removed; service principal with only Reader role; typo in resource group after cluster rename; subscription/tenant mismatch in credentials.

Related errors


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