kubernetes/kops · error
getting VMSS: %w
Error message
getting VMSS: %w
What it means
This error wraps any failure from the Azure SDK VirtualMachineScaleSetsClient.Get call when kOps fetches a VMSS definition (with UserData expanded) from an Azure resource group. It is a thin wrapper: the underlying azcore/azidentity error (404, 401, 403, throttling, network) is preserved via %w. kOps throws it so callers can identify the operation (reading a scale set) while retaining the original SDK error for errors.Is/As inspection.
Source
Thrown at upup/pkg/fi/cloudup/azure/vmscaleset.go:83
if err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.ErrorCode == "ResourceGroupNotFound" {
return nil, nil
}
return nil, fmt.Errorf("listing VMSSs: %w", err)
}
l = append(l, resp.Value...)
}
return l, nil
}
func (c *vmScaleSetsClientImpl) Get(ctx context.Context, resourceGroupName string, vmssName string) (*compute.VirtualMachineScaleSet, error) {
opts := &compute.VirtualMachineScaleSetsClientGetOptions{
Expand: to.Ptr(compute.ExpandTypesForGetVMScaleSetsUserData),
}
resp, err := c.c.Get(ctx, resourceGroupName, vmssName, opts)
if err != nil {
return nil, fmt.Errorf("getting VMSS: %w", err)
}
return &resp.VirtualMachineScaleSet, nil
}
func (c *vmScaleSetsClientImpl) Delete(ctx context.Context, resourceGroupName, vmssName string) error {
future, err := c.c.BeginDelete(ctx, resourceGroupName, vmssName, nil)
if err != nil {
return fmt.Errorf("deleting VMSS: %w", err)
}
if _, err := future.PollUntilDone(ctx, nil); err != nil {
return fmt.Errorf("waiting for VMSS deletion completion: %w", err)
}
return nil
}
func newVMScaleSetsClientImpl(subscriptionID string, cred *azidentity.DefaultAzureCredential) (*vmScaleSetsClientImpl, error) {
c, err := compute.NewVirtualMachineScaleSetsClient(subscriptionID, cred, nil)
if err != nil {View on GitHub (pinned to 4c8573c808)
Solutions
- Verify the VMSS name and resource group are correct: az vmss list -g <resourceGroup> -o table
- Confirm RBAC: grant the identity 'Contributor' (or at least Reader) on the cluster resource group
- Check AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID and credential env vars match the cluster's subscription
- Unwrap with errors.As to check azcore.ResponseError and inspect StatusCode (404 vs 401/429) to pick the right fix
- Retry if the error is 429 or a transient network failure
Example fix
// before
vmss, err := cloud.AzureCloud().VMScaleSets().Get(ctx, rg, vmssName)
if err != nil { return fmt.Errorf("getting VMSS: %w", err) }
// after
vmss, err := cloud.AzureCloud().VMScaleSets().Get(ctx, rg, vmssName)
if err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.StatusCode == 404 {
return nil // treat as not-found instead of aborting
}
return fmt.Errorf("getting VMSS %q in rg %q: %w", vmssName, rg, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: verify preconditions before the ARM call
if vmssName == "" || resourceGroupName == "" {
return fmt.Errorf("VMSS name and resource group must be non-empty")
}
// optionally: rgExists, _ := groupsClient.Get(ctx, resourceGroupName, nil)
// if rgExists.StatusCode == 404 { return fmt.Errorf("resource group %q missing", resourceGroupName) } Type guard
func isNotFoundErr(err error) bool {
var respErr *azcore.ResponseError
return errors.As(err, &respErr) && respErr.StatusCode == http.StatusNotFound
} Try / catch
vmss, err := client.Get(ctx, rg, vmssName)
if err != nil {
var respErr *azcore.ResponseError
switch {
case errors.As(err, &respErr) && respErr.StatusCode == 404:
return nil // handle not-found gracefully
case errors.As(err, &respErr) && respErr.StatusCode == 429:
// back off and retry per Retry-After header
default:
return fmt.Errorf("getting VMSS: %w", err)
}
} Prevention
- Validate VMSS/resource-group names against the cluster spec before ARM calls
- Grant the kOps identity at least Reader on the cluster resource group
- Set AZURE_SUBSCRIPTION_ID/TENANT_ID correctly in every environment (CI, local)
- Check azcore.ResponseError.StatusCode to distinguish 404/401/429 handling
- Wrap ARM calls with bounded retry/backoff for 429 and transient errors
When it happens
Trigger: vmScaleSetsClientImpl.Get is invoked while resolving or verifying a VMSS (e.g. during Azure cluster reconciliation or instance group operations) and the ARM API call fails: VMSS does not exist in the given resource group, subscription mismatch, RBAC lacks 'Reader' on the scale set, ARM throttling (429), or transient network/DNS failure reaching management.azure.com.
Common situations: Typo in the VMSS name or resource group in kOps cluster spec; cluster spec references a scale set deleted out-of-band in the Azure portal; azidentity credentials not authorized for the subscription (wrong AZURE_TENANT_ID/AZURE_SUBSCRIPTION_ID env vars); corporate proxy blocking ARM endpoints; ARM API throttling on very large clusters.
Related errors
- deleting VMSS: %w
- listing VMSS VMs: %w
- expected exactly one subnet for InstanceGroup %q; subnets wa
- unexpected subnet type: for InstanceGroup %q; type was %s
- instance group must have the same min and max size in Azure,
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/722a4a65fc6c4e66.
Report an issue: GitHub.