{"record":{"id":"97d079d9cdc1058b","repo":"kubernetes/kops","slug":"listing-disks-w","errorCode":null,"errorMessage":"listing disks: %w","messagePattern":"listing disks: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/disk.go","lineNumber":68,"sourceCode":"\t}\n\treturn &resp.Disk, err\n}\n\nfunc (c *disksClientImpl) List(ctx context.Context, resourceGroupName string) ([]*compute.Disk, error) {\n\tif resourceGroupName == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tvar l []*compute.Disk\n\tpager := c.c.NewListByResourceGroupPager(resourceGroupName, nil)\n\tfor pager.More() {\n\t\tresp, err := pager.NextPage(ctx)\n\t\tif err != nil {\n\t\t\tvar respErr *azcore.ResponseError\n\t\t\tif errors.As(err, &respErr) && respErr.ErrorCode == \"ResourceGroupNotFound\" {\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"listing disks: %w\", err)\n\t\t}\n\t\tl = append(l, resp.Value...)\n\t}\n\treturn l, nil\n}\n\nfunc (c *disksClientImpl) Delete(ctx context.Context, resourceGroupName, diskName string) error {\n\tfuture, err := c.c.BeginDelete(ctx, resourceGroupName, diskName, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"deleting disk: %w\", err)\n\t}\n\tif _, err := future.PollUntilDone(ctx, nil); err != nil {\n\t\treturn fmt.Errorf(\"waiting for disk deletion completion: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc newDisksClientImpl(subscriptionID string, cred *azidentity.DefaultAzureCredential) (*disksClientImpl, error) {","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/disk.go#L50-L86","documentation":"DisksClient.List pages through all disks in a resource group via NewListByResourceGroupPager. ResourceGroupNotFound is explicitly treated as an empty list, but any other pager failure is wrapped as \"listing disks: %w\". This is a read-path error: the caller (typically cluster teardown/fuzzing code looking for orphaned disks) cannot enumerate existing disks.","triggerScenarios":"Calling DisksClient.List when a paging NextPage call fails for reasons other than ResourceGroupNotFound: invalid/missing credentials (401), RBAC missing Microsoft.Compute/disks/read (403), invalid subscription ID, network failure, or ARM throttling during pagination.","commonSituations":"Running kOps with an Azure identity lacking Reader on the resource group; an expired az login/SP secret; wrong AZURE_SUBSCRIPTION_ID env var; transient network outage during a multi-page listing; tenant/subscription misconfiguration in the cloud config.","solutions":["Unwrap and check *azcore.ResponseError: 401 means re-authenticate (az login, refresh SP secret, fix managed identity); 403 means grant Microsoft.Compute/disks/read on the resource group.","Verify AZURE_TENANT_ID / AZURE_SUBSCRIPTION_ID / client credentials are set and correct in the environment or azure-cloud-provider config.","Confirm the resource group name is correct and exists in the configured subscription.","For transient network/429 errors, retry the List with exponential backoff."],"exampleFix":"// caller-side handling\nif _, err := disks.List(ctx, rg); err != nil {\n    var respErr *azcore.ResponseError\n    if errors.As(err, &respErr) && respErr.StatusCode == 403 {\n        klog.Warningf(\"missing disks/read permission on %s: %v\", rg, err)\n    }\n}","handlingStrategy":"type-guard","validationCode":"if resourceGroupName == \"\" {\n    return nil, nil // matches the client's own empty-rg behavior\n}\ncred, err := azidentity.NewDefaultAzureCredential(nil)\nif err != nil {\n    return fmt.Errorf(\"no Azure credentials available: %w\", err)\n}","typeGuard":"func isAuthError(err error) bool {\n    var respErr *azcore.ResponseError\n    return errors.As(err, &respErr) && (respErr.StatusCode == 401 || respErr.StatusCode == 403)\n}","tryCatchPattern":"if err != nil {\n    var respErr *azcore.ResponseError\n    if errors.As(err, &respErr) {\n        switch {\n        case respErr.ErrorCode == \"ResourceGroupNotFound\":\n            return nil // treat as empty, like the client does\n        case respErr.StatusCode == 401 || respErr.StatusCode == 403:\n            return fmt.Errorf(\"credentials/permissions insufficient for listing disks: %w\", err)\n        default:\n            return retryableOrWrap(err)\n        }\n    }\n}","preventionTips":["Ensure the identity used by kOps has Reader (or Contributor) on all cluster resource groups.","Keep AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID, and client credentials current; rotate SP secrets before expiry.","Treat ResourceGroupNotFound as an empty result in callers so first-time/teardown flows don't abort."],"tags":["azure","disk","listing","pagination"],"backgroundTag":"azure-list-resources-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"}