{"record":{"id":"811dd7769af1a318","repo":"kubernetes/kops","slug":"waiting-for-disk-create-update-completion-w","errorCode":null,"errorMessage":"waiting for disk create/update completion: %w","messagePattern":"waiting for disk create/update completion: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/disk.go","lineNumber":49,"sourceCode":"\tCreateOrUpdate(ctx context.Context, resourceGroupName, diskName string, parameters compute.Disk) (*compute.Disk, error)\n\tList(ctx context.Context, resourceGroupName string) ([]*compute.Disk, error)\n\tDelete(ctx context.Context, resourceGroupName, diskname string) error\n}\n\ntype disksClientImpl struct {\n\tc *compute.DisksClient\n}\n\nvar _ DisksClient = (*disksClientImpl)(nil)\n\nfunc (c *disksClientImpl) CreateOrUpdate(ctx context.Context, resourceGroupName, diskName string, parameters compute.Disk) (*compute.Disk, error) {\n\tfuture, err := c.c.BeginCreateOrUpdate(ctx, resourceGroupName, diskName, parameters, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating/updating disk: %w\", err)\n\t}\n\tresp, err := future.PollUntilDone(ctx, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"waiting for disk create/update completion: %w\", err)\n\t}\n\treturn &resp.Disk, err\n}\n\nfunc (c *disksClientImpl) List(ctx context.Context, resourceGroupName string) ([]*compute.Disk, error) {\n\tif resourceGroupName == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tvar l []*compute.Disk\n\tpager := c.c.NewListByResourceGroupPager(resourceGroupName, nil)\n\tfor pager.More() {\n\t\tresp, err := pager.NextPage(ctx)\n\t\tif err != nil {\n\t\t\tvar respErr *azcore.ResponseError\n\t\t\tif errors.As(err, &respErr) && respErr.ErrorCode == \"ResourceGroupNotFound\" {\n\t\t\t\treturn nil, nil\n\t\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/disk.go#L31-L67","documentation":"After BeginCreateOrUpdate accepts the request, CreateOrUpdate polls the returned future with PollUntilDone until the ARM long-running operation finishes. If polling fails (operation error, context cancellation, or transient HTTP failure mid-poll), the error is wrapped as \"waiting for disk create/update completion: %w\". This means the request was accepted but the disk never reached a final successful state within the call.","triggerScenarios":"Calling DisksClient.CreateOrUpdate where the accepted LRO subsequently fails or hangs: context deadline/timeout exceeded during PollUntilDone, ARM returns a failed provisioning state (e.g. disk size/SKU not supported in region), 429 throttling during polling, or the operation is cancelled upstream.","commonSituations":"Short context timeouts on slow Azure regions where disk creation takes minutes; region/SKU combination unavailable (e.g. Premium_ZRS not offered); subscription quota hit while the operation is in flight; node provisioning interrupted so the ctx passed in is cancelled.","solutions":["Unwrap to check for context.DeadlineExceeded/Canceled: if so, re-check the disk's actual state via DisksClient.List or the ARM portal before retrying, since the operation may still complete.","Increase the context timeout passed to CreateOrUpdate (disk creation can take several minutes).","Inspect the wrapped *azcore.ResponseError for provisioning failure details (ErrorCode) and fix the underlying cause (SKU/region/quota).","Handle 429 by backing off and retrying the poll or the whole operation."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\n// after\ndiskCtx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)\n_, err := disks.CreateOrUpdate(diskCtx, rg, name, params)","handlingStrategy":"retry","validationCode":"if ctx.Err() != nil {\n    return fmt.Errorf(\"context already done before disk create/update: %w\", ctx.Err())\n}\n// ensure generous deadline for LROs\nctx, cancel := context.WithTimeout(ctx, 15*time.Minute)\ndefer cancel()","typeGuard":"func isContextError(err error) bool {\n    return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled)\n}","tryCatchPattern":"if err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        // do NOT immediately recreate: verify the disk's actual state first\n        existing, listErr := disks.List(ctx, rg)\n        if listErr == nil && findDisk(existing, diskName) != nil {\n            return nil // operation actually completed\n        }\n    }\n    return fmt.Errorf(\"disk LRO failed: %w\", err)\n}","preventionTips":["Always pass a context with a timeout of at least 10-15 minutes for disk LROs.","On poll failure, check actual disk state via List/Get before retrying to avoid duplicate create conflicts.","Monitor Azure status/region capacity if operations repeatedly hang or fail mid-provisioning."],"tags":["azure","disk","long-running-operation","timeout"],"backgroundTag":"long-running-operation-failed","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"}