{"record":{"id":"49c530da1c5148e7","repo":"kubernetes/kops","slug":"os-disk-is-required-for-vmscaleset-q","errorCode":null,"errorMessage":"os disk is required for VMScaleSet %q","messagePattern":"os disk is required for VMScaleSet %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azuretasks/vmscaleset_terraform.go","lineNumber":100,"sourceCode":"\tDisablePasswordAuthentication *bool                                       `cty:\"disable_password_authentication\"`\n\tAdminSSHKey                   []*terraformAzureVMScaleSetSSHKey           `cty:\"admin_ssh_key\"`\n\tSourceImageReference          *terraformAzureVMScaleSetImageReference     `cty:\"source_image_reference\"`\n\tSourceImageID                 *string                                     `cty:\"source_image_id\"`\n\tOSDisk                        *terraformAzureVMScaleSetOSDisk             `cty:\"os_disk\"`\n\tNetworkInterface              []*terraformAzureVMScaleSetNetworkInterface `cty:\"network_interface\"`\n\tIdentity                      *terraformAzureVMScaleSetIdentity           `cty:\"identity\"`\n\tUserData                      *terraformWriter.Literal                    `cty:\"user_data\"`\n\tTags                          map[string]string                           `cty:\"tags\"`\n}\n\nfunc (*VMScaleSet) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *VMScaleSet) error {\n\tif e.StorageProfile == nil || e.StorageProfile.VirtualMachineScaleSetStorageProfile == nil {\n\t\treturn fmt.Errorf(\"storage profile is required for VMScaleSet %q\", fi.ValueOf(e.Name))\n\t}\n\n\tstorageProfile := e.StorageProfile.VirtualMachineScaleSetStorageProfile\n\tif storageProfile.OSDisk == nil {\n\t\treturn fmt.Errorf(\"os disk is required for VMScaleSet %q\", fi.ValueOf(e.Name))\n\t}\n\n\tupgradeMode := string(compute.UpgradeModeManual)\n\tdisablePasswordAuthentication := true\n\ttf := &terraformAzureVMScaleSet{\n\t\tName:                          e.Name,\n\t\tResourceGroupName:             e.ResourceGroup.terraformName(),\n\t\tLocation:                      new(t.Cloud.Region()),\n\t\tSKU:                           e.SKUName,\n\t\tInstances:                     e.Capacity,\n\t\tZones:                         stringSlice(e.Zones),\n\t\tUpgradeMode:                   &upgradeMode,\n\t\tComputerNamePrefix:            e.ComputerNamePrefix,\n\t\tAdminUsername:                 e.AdminUser,\n\t\tDisablePasswordAuthentication: &disablePasswordAuthentication,\n\t\tAdminSSHKey: []*terraformAzureVMScaleSetSSHKey{\n\t\t\t{\n\t\t\t\tUsername:  e.AdminUser,","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azuretasks/vmscaleset_terraform.go#L82-L118","documentation":"This error is thrown by the Azure VM ScaleSet terraform task when rendering Terraform JSON. kOps requires that a VM ScaleSet define both a storage profile and, within it, an OSDisk; without an OS disk the scale set cannot boot any instances, so RenderTerraform refuses to emit a partial/invalid resource. It is a fail-fast validation before building the terraformAzureVMScaleSet struct.","triggerScenarios":"RenderTerraform is invoked on a VMScaleSet task whose e.StorageProfile is non-nil and passes the first check, but e.StorageProfile.VirtualMachineScaleSetStorageProfile.OSDisk is nil — i.e. the task was constructed (typically from an Azure model context building instance groups) without setting an OS disk.","commonSituations":"A custom Azure model template or newer/patched kOps code path forgets to populate OSDisk when assembling the storage profile; an upgrade where a previously-populated OSDisk field is dropped during task copying; hand-edited cluster spec or controller code creating VMScaleSet tasks directly.","solutions":["Find where the VMScaleSet task is built for your instance group (upup/pkg/fi/cloudup/azure package model code) and ensure StorageProfile.VirtualMachineScaleSetStorageProfile.OSDisk is assigned","Inspect e.StorageProfile itself: if it is also nil, fix the earlier 'storage profile is required' path — build the whole VirtualMachineScaleSetStorageProfile","If this came from custom code, copy the OSDisk population from the stock azure model (ManagedDisk, OSType, DiskSizeGB, Caching) and re-render","If this is stock kOps failing, file an issue with the cluster spec and kops version, and try a newer kOps release"],"exampleFix":"// before\nstorageProfile := &compute.VirtualMachineScaleSetStorageProfile{}\ntf := &terraformAzureVMScaleSet{ ... }\n// after\nstorageProfile := &compute.VirtualMachineScaleSetStorageProfile{\n    OSDisk: &compute.VirtualMachineScaleSetOSDisk{\n        ManagedDisk: &compute.VirtualMachineScaleSetManagedDiskParameters{ StorageAccountType: storageType },\n        OSType:      compute.OperatingSystemTypesLinux,\n        Caching:     compute.CachingTypesReadWrite,\n    },\n}\ntf := &terraformAzureVMScaleSet{ ... }","handlingStrategy":"validation","validationCode":"if ss.StorageProfile == nil || ss.StorageProfile.VirtualMachineScaleSetStorageProfile == nil {\n    return fmt.Errorf(\"VMScaleSet %s: storage profile missing\", name)\n}\nif ss.StorageProfile.VirtualMachineScaleSetStorageProfile.OSDisk == nil {\n    return fmt.Errorf(\"VMScaleSet %s: OSDisk missing\", name)\n}","typeGuard":"func hasOSDisk(ss *compute.VirtualMachineScaleSet) bool {\n    return ss != nil && ss.StorageProfile != nil &&\n        ss.StorageProfile.VirtualMachineScaleSetStorageProfile != nil &&\n        ss.StorageProfile.VirtualMachineScaleSetStorageProfile.OSDisk != nil\n}","tryCatchPattern":null,"preventionTips":["Always construct VMSS storage profiles via a helper that requires OSDisk as a parameter","Unit-test your Azure model code against RenderTerraform for every instance group type","Keep OSDisk population code adjacent to StorageProfile creation so they cannot drift apart"],"tags":["azure","terraform","vmss","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}