{"record":{"id":"9a88503bd7af23b1","repo":"kubernetes/kops","slug":"deleting-resource-group-w","errorCode":null,"errorMessage":"deleting resource group: %w","messagePattern":"deleting resource group: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/resourcegroup.go","lineNumber":61,"sourceCode":"}\n\nfunc (c *resourceGroupsClientImpl) List(ctx context.Context) ([]*resources.ResourceGroup, error) {\n\tvar l []*resources.ResourceGroup\n\tpager := c.c.NewListPager(nil)\n\tfor pager.More() {\n\t\tresp, err := pager.NextPage(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"listing resource groups: %w\", err)\n\t\t}\n\t\tl = append(l, resp.Value...)\n\t}\n\treturn l, nil\n}\n\nfunc (c *resourceGroupsClientImpl) Delete(ctx context.Context, name string) error {\n\tfuture, err := c.c.BeginDelete(ctx, name, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"deleting resource group: %w\", err)\n\t}\n\tif _, err = future.PollUntilDone(ctx, nil); err != nil {\n\t\treturn fmt.Errorf(\"waiting for resource group deletion completion: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc newResourceGroupsClientImpl(subscriptionID string, cred *azidentity.DefaultAzureCredential) (*resourceGroupsClientImpl, error) {\n\tc, err := resources.NewResourceGroupsClient(subscriptionID, cred, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating resource group client: %w\", err)\n\t}\n\treturn &resourceGroupsClientImpl{\n\t\tc: c,\n\t}, nil\n}\n","sourceCodeStart":43,"sourceCodeEnd":78,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/resourcegroup.go#L43-L78","documentation":"Wraps the immediate failure of resources.ResourceGroupsClient.BeginDelete, the call that starts asynchronous deletion of a resource group. This is the request-rejection stage; a later poll failure produces the separate 'waiting for resource group deletion completion' error.","triggerScenarios":"resourceGroupsClientImpl.Delete(ctx, name) where BeginDelete fails: resource group already gone (ResourceGroupNotFound), RBAC denies Microsoft.Resources/subscriptions/resourceGroups/delete, or the group is locked (ReadOnly/CanNotDelete management lock).","commonSituations":"Re-running cluster deletion after a partial teardown (group already deleted); a subscription-level management lock left from an earlier maintenance window; insufficient Contributor role.","solutions":["Check the wrapped ResponseError: ResourceGroupNotFound means deletion already done — treat as success","Remove any Azure management locks (ReadOnly/CanNotDelete) on the resource group","Ensure the identity has the delete permission (Contributor or Owner at subscription/group scope)","Confirm the resource group name matches the kOps cluster's cluster-name-based group"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"az lock list -g $RG -o table            # no ReadOnly/CanNotDelete locks\naz group show -n $RG -o none            # group exists and identity can access it","typeGuard":"func isNotFoundOrAlreadyGone(err error) bool {\n  var re *azcore.ResponseError\n  if !errors.As(err, &re) { return false }\n  return re.StatusCode == 404 || re.ErrorCode == \"ResourceGroupNotFound\"\n}","tryCatchPattern":"err := rgClient.Delete(ctx, name)\nvar re *azcore.ResponseError\nif errors.As(err, &re) {\n  if re.StatusCode == 404 { return nil /* already deleted; idempotent */ }\n  if re.ErrorCode == \"RequestDisallowedByPolicy\" || strings.Contains(re.ErrorCode, \"ScopeLock\") {\n    return fmt.Errorf(\"remove management lock before deleting group %s\", name)\n  }\n}","preventionTips":["Check for Azure management locks before teardown","Make delete paths idempotent by swallowing 404","Grant Contributor/Owner to the automation identity","Delete clusters once at a time to avoid double-teardown races"],"tags":["azure","resource-groups","delete","error-wrapping"],"backgroundTag":"azure-resource-delete-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"}