kubernetes/kops · error
error listing disks: %s
Error message
error listing disks: %s
What it means
kOps' azureCloudImplementation.FindClusterStatus fails while listing managed disks in the cluster resource group via c.Disk().List. Cluster status discovery depends on enumerating tagged etcd volumes, so the whole status lookup fails. Note it uses %s (not %w), so the chain is not unwrappable.
Source
Thrown at upup/pkg/fi/cloudup/azure/status.go:38
"context"
"fmt"
"strings"
compute "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute"
v1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/cloudinstances"
"k8s.io/kops/pkg/etcd"
"k8s.io/kops/upup/pkg/fi"
)
// FindClusterStatus discovers the status of the cluster by looking for the tagged etcd volume.
func (c *azureCloudImplementation) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
klog.V(2).Infof("Listing Azure managed disks.")
disks, err := c.Disk().List(context.TODO(), cluster.AzureResourceGroupName())
if err != nil {
return nil, fmt.Errorf("error listing disks: %s", err)
}
etcdStatus, err := c.findEtcdStatus(disks)
if err != nil {
return nil, err
}
status := &kops.ClusterStatus{
EtcdClusters: etcdStatus,
}
klog.V(2).Infof("Cluster status (from cloud): %v", fi.DebugAsJsonString(status))
return status, nil
}
func (c *azureCloudImplementation) findEtcdStatus(disks []*compute.Disk) ([]kops.EtcdClusterStatus, error) {
statusMap := make(map[string]*kops.EtcdClusterStatus)
for _, disk := range disks {
if !c.isDiskForCluster(disk) {
continueView on GitHub (pinned to 4c8573c808)
Solutions
- Verify the cluster's resource group name exists (az group show -n <rg>)
- Grant the identity Microsoft.Compute/disks/read on the resource group
- Fix the root cause inside Disk().List; consider switching to %w wrapping for unwrappability
- Retry on throttling honoring Retry-After
Example fix
// before
return nil, fmt.Errorf("error listing disks: %s", err)
// after
return nil, fmt.Errorf("error listing disks: %w", err) Defensive patterns
Strategy: try-catch
Validate before calling
groups, err := rgClient.Get(ctx, cluster.AzureResourceGroupName(), nil)
if err != nil {
return fmt.Errorf("resource group for cluster missing: %w", err)
} Type guard
var respErr *azcore.ResponseError
if errors.As(err, &respErr) {
if respErr.ErrorCode == "ResourceGroupNotFound" {
// cluster fully deleted; return empty status instead of failing
}
} Try / catch
status, err := cloud.FindClusterStatus(cluster)
if err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.StatusCode == 403 {
return fmt.Errorf("need Microsoft.Compute/disks/read on %s", cluster.AzureResourceGroupName())
}
return err
} Prevention
- Grant the identity disk read access on the cluster resource group
- Verify the resource group exists before status discovery
- Prefer %w over %s wrapping so callers can errors.As on ResponseError
When it happens
Trigger: Disk().List(ctx, cluster.AzureResourceGroupName()) returns error: nonexistent resource group, 403 missing Microsoft.Compute/disks/read, throttling, or transient ARM 5xx.
Common situations: kops get cluster --cloud=azure against a cluster whose resource group was deleted; identity without disk read permissions; Azure API throttling in a busy subscription.
Related errors
- parsing etcd backup-store %q: %w
- expected azureblob:// backup-store, got %q
- parsing configStore.base %q: %w
- backup-store %q is azureblob:// but configStore.base %q is n
- error parsing etcd cluster tag %q on volume %q: %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/fc7cc13c3f454fde.
Report an issue: GitHub.