kubernetes/kops · error

creating/updating VMSS: %w

Error message

creating/updating VMSS: %w

What it means

Wrapped when the initial BeginCreateOrUpdate call to the VirtualMachineScaleSets client fails synchronously in vmScaleSetsClientImpl.CreateOrUpdate. The VMSS PUT never became a long-running future; the ARM error (invalid VMSS profile, RBAC, quota, image reference) is preserved via %w. Distinct from the later 'waiting for VMSS create/update' polling error.

Source

Thrown at upup/pkg/fi/cloudup/azure/vmscaleset.go:47

// VMScaleSetsClient is a client for managing VMSSs.
type VMScaleSetsClient interface {
	CreateOrUpdate(ctx context.Context, resourceGroupName, vmScaleSetName string, parameters compute.VirtualMachineScaleSet) (*compute.VirtualMachineScaleSet, error)
	List(ctx context.Context, resourceGroupName string) ([]*compute.VirtualMachineScaleSet, error)
	Get(ctx context.Context, resourceGroupName string, vmssName string) (*compute.VirtualMachineScaleSet, error)
	Delete(ctx context.Context, resourceGroupName, vmssName string) error
}

type vmScaleSetsClientImpl struct {
	c *compute.VirtualMachineScaleSetsClient
}

var _ VMScaleSetsClient = (*vmScaleSetsClientImpl)(nil)

func (c *vmScaleSetsClientImpl) CreateOrUpdate(ctx context.Context, resourceGroupName, vmScaleSetName string, parameters compute.VirtualMachineScaleSet) (*compute.VirtualMachineScaleSet, error) {
	future, err := c.c.BeginCreateOrUpdate(ctx, resourceGroupName, vmScaleSetName, parameters, nil)
	if err != nil {
		return nil, fmt.Errorf("creating/updating VMSS: %w", err)
	}
	resp, err := future.PollUntilDone(ctx, nil)
	if err != nil {
		return nil, fmt.Errorf("waiting for VMSS create/update: %w", err)
	}
	return &resp.VirtualMachineScaleSet, nil
}

func (c *vmScaleSetsClientImpl) List(ctx context.Context, resourceGroupName string) ([]*compute.VirtualMachineScaleSet, error) {
	if resourceGroupName == "" {
		return nil, nil
	}

	var l []*compute.VirtualMachineScaleSet
	pager := c.c.NewListPager(resourceGroupName, nil)
	for pager.More() {
		resp, err := pager.NextPage(ctx)
		if err != nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped azcore.ResponseError (StatusCode/ErrorCode) for the exact ARM rejection
  2. Validate the VMSS parameters from the kops instance group spec: vmSize, image, subnet ID, SSH keys
  3. Ensure the service principal has Contributor/Network Contributor + compute write on the resource group
  4. Verify the referenced subnet/vnet exists before creating the VMSS

Example fix

// before: referencing subnet that does not exist yet
IPConfigurations: []*compute.VirtualMachineScaleSetIPConfiguration{{ Subnet: &compute.APIEntityReference{ID: to.Ptr(badSubnetID)} }}
// after: use the subnet created by the kops vnet task
IPConfigurations: []*compute.VirtualMachineScaleSetIPConfiguration{{ Subnet: &compute.APIEntityReference{ID: to.Ptr(subnet.ID)} }}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-validate VMSS parameters before create/update
if parameters.Location == nil || parameters.VirtualMachineProfile == nil || parameters.VirtualMachineProfile.StorageProfile == nil {
    return fmt.Errorf("VMSS %s/%s missing location or VM profile", resourceGroupName, vmScaleSetName)
}
// confirm the target subnet exists
if _, err := subnetsClient.Get(ctx, rg, vnetName, subnetName, nil); err != nil {
    return fmt.Errorf("subnet %s referenced by VMSS not found: %w", subnetName, err)
}

Type guard

func armQuotaOrCapacity(err error) bool {
    var respErr *azcore.ResponseError
    return errors.As(err, &respErr) && (respErr.StatusCode == http.StatusConflict || respErr.StatusCode == http.StatusTooManyRequests)
}

Try / catch

vmss, err := vmssClient.CreateOrUpdate(ctx, rg, name, parameters)
if err != nil {
    var respErr *azcore.ResponseError
    if errors.As(err, &respErr) {
        if respErr.StatusCode == http.StatusForbidden {
            return fmt.Errorf("grant compute write RBAC on %s: %w", rg, err)
        }
        if respErr.StatusCode == http.StatusBadRequest {
            return fmt.Errorf("invalid VMSS spec (vmSize/image/subnet): %w", err)
        }
    }
    return err
}

Prevention

When it happens

Trigger: CreateOrUpdate calls c.c.BeginCreateOrUpdate(ctx, resourceGroupName, vmScaleSetName, parameters, nil) and the SDK errors immediately: malformed VirtualMachineScaleSet parameters (bad vmImage/instance type/SSH config), missing Microsoft.Compute/virtualMachineScaleSets/write permission, wrong resource group, or network failure.

Common situations: Invalid instance type or image reference in the kops instance group; spot/max-p price constraints invalid; subnet reference pointing to a not-yet-created vnet; RBAC-restricted service principal; ARM throttling on create.

Related errors


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