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) {
			continue

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the cluster's resource group name exists (az group show -n <rg>)
  2. Grant the identity Microsoft.Compute/disks/read on the resource group
  3. Fix the root cause inside Disk().List; consider switching to %w wrapping for unwrappability
  4. 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

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


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