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
- Read the wrapped azcore.ResponseError (StatusCode/ErrorCode) for the exact ARM rejection
- Validate the VMSS parameters from the kops instance group spec: vmSize, image, subnet ID, SSH keys
- Ensure the service principal has Contributor/Network Contributor + compute write on the resource group
- 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
- Validate instance type, image reference, and subnet ID in the instance group before apply
- Ensure the vnet/subnet tasks complete before VMSS creation
- Grant Contributor (compute + network write) to the kops principal
- Watch for ARM 429s and respect Retry-After
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
- waiting for VMSS create/update: %w
- listing VMSSs: %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/6d287682b2d7cea1.
Report an issue: GitHub.