kubernetes/kops · error

deleting disk: %w

Error message

deleting disk: %w

What it means

DisksClient.Delete starts an ARM long-running delete operation with BeginDelete and, if that synchronous call fails (before a future is created), wraps the error as "deleting disk: %w". Common wrapped causes are the disk not being found, insufficient RBAC for Microsoft.Compute/disks/delete, auth failures, or an already-in-progress conflicting operation.

Source

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

	pager := c.c.NewListByResourceGroupPager(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 disks: %w", err)
		}
		l = append(l, resp.Value...)
	}
	return l, nil
}

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

func newDisksClientImpl(subscriptionID string, cred *azidentity.DefaultAzureCredential) (*disksClientImpl, error) {
	c, err := compute.NewDisksClient(subscriptionID, cred, nil)
	if err != nil {
		return nil, fmt.Errorf("creating disks client: %w", err)
	}
	return &disksClientImpl{
		c: c,
	}, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Unwrap and inspect *azcore.ResponseError: on 404 treat the disk as already deleted and continue; on 409 detach the disk from its VM (or wait for the in-flight operation) before deleting.
  2. Verify the Azure identity has Microsoft.Compute/disks/delete permission on the resource group.
  3. Refresh authentication credentials (az login / SP secret) if the error is 401.
  4. Make deletion idempotent in callers: ignore NotFound errors so repeated destroy runs succeed.

Example fix

// before (fails on missing disk)
if err := disks.Delete(ctx, rg, diskName); err != nil { return err }
// after
if err := disks.Delete(ctx, rg, diskName); err != nil {
    var respErr *azcore.ResponseError
    if !(errors.As(err, &respErr) && respErr.StatusCode == 404) {
        return err
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

existing, err := disks.List(ctx, resourceGroupName)
if err == nil && findDiskByName(existing, diskName) == nil {
    return nil // disk already gone; skip delete
}

Type guard

func isNotFound(err error) bool {
    var respErr *azcore.ResponseError
    return errors.As(err, &respErr) && (respErr.StatusCode == 404 || respErr.ErrorCode == "ResourceNotFound")
}

Try / catch

if err := disks.Delete(ctx, rg, diskName); err != nil {
    var respErr *azcore.ResponseError
    if errors.As(err, &respErr) {
        if respErr.StatusCode == 404 {
            return nil // already deleted; idempotent success
        }
        if respErr.StatusCode == 409 {
            return fmt.Errorf("disk still attached or busy; detach and retry: %w", err)
        }
    }
    return fmt.Errorf("disk delete failed: %w", err)
}

Prevention

When it happens

Trigger: Calling DisksClient.Delete where the ARM API rejects the initial BeginDelete request: 404 disk name not found in the resource group, 403 missing delete permission, 401 authentication failure, 409 conflict (disk attached to a VM or another operation in flight), or 429 throttling.

Common situations: Cluster teardown trying to delete a disk that was already removed by a concurrent job; deleting disks still attached to VMs; service principal missing Contributor on the node resource group; expired credentials during long-running destroy operations.

Related errors


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