{"record":{"id":"2a6a66dfbb5fa559","repo":"kubernetes/kops","slug":"error-resizing-akamai-linode-volume-q-w","errorCode":null,"errorMessage":"error resizing Akamai (Linode) volume %q: %w","messagePattern":"error resizing Akamai \\(Linode\\) volume %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/linodetasks/volume.go","lineNumber":132,"sourceCode":"\t\tif expected.SizeGB == nil {\n\t\t\treturn fi.RequiredField(\"SizeGB\")\n\t\t}\n\t\tif fi.ValueOf(expected.SizeGB) < 10 {\n\t\t\treturn fmt.Errorf(\"SizeGB must be at least 10 GB\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (*Volume) RenderLinode(t *linode.APITarget, actual, expected, changes *Volume) error {\n\tif actual != nil {\n\t\texpected.ID = actual.ID\n\t\tif changes.SizeGB == nil {\n\t\t\treturn nil\n\t\t}\n\t\tif err := t.Cloud.Client().ResizeVolume(context.Background(), fi.ValueOf(actual.ID), linodego.VolumeResizeOptions{Size: fi.ValueOf(expected.SizeGB)}); err != nil {\n\t\t\treturn fmt.Errorf(\"error resizing Akamai (Linode) volume %q: %w\", fi.ValueOf(actual.Name), err)\n\t\t}\n\t\tklog.V(2).Infof(\"Resized Akamai (Linode) volume %q (id=%d) to %d GB\", fi.ValueOf(actual.Name), fi.ValueOf(actual.ID), fi.ValueOf(expected.SizeGB))\n\t\treturn nil\n\t}\n\n\tname := fi.ValueOf(expected.Name)\n\tlabel := truncate.TruncateString(linode.NormalizeLinodeLabel(name), truncate.TruncateStringOptions{MaxLength: 32})\n\tcreated, err := t.Cloud.Client().CreateVolume(context.Background(), linodego.VolumeCreateOptions{\n\t\tLabel:  label,\n\t\tRegion: fi.ValueOf(expected.Region),\n\t\tSize:   fi.ValueOf(expected.SizeGB),\n\t\tTags:   expected.Tags,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating Akamai (Linode) volume %q: %w\", name, err)\n\t}\n\n\texpected.ID = new(created.ID)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/linodetasks/volume.go#L114-L150","documentation":"This error wraps a failure from the Linode API call ResizeVolume when kOps' RenderLinode tries to grow an existing block-storage volume to the size declared in the cluster spec. It is only reached when the volume already exists (actual != nil) and the diff contains a SizeGB change. The underlying linodego error (auth, quota, invalid size, volume attached to a powered-on instance, etc.) is preserved via %w.","triggerScenarios":"An existing Linode Volume is found by Find(), the cluster spec sets a larger SizeGB, and the ResizeVolume API call fails - e.g. the volume is currently attached to a running Linode instance, the requested size exceeds the account volume-size quota, or the API returns 4xx/5xx (invalid token, size above region max of 10240 GB, transient server error).","commonSituations":"Users edit instanceGroup/cluster yaml to enlarge persistent storage during an upgrade or 'kops update' run while the volume is attached to a booted node; accounts hitting the default volume quota; typos in cluster spec producing a size larger than the region limit.","solutions":["Detach/unattach the volume or shut down the Linode instance it is attached to (Linode cannot resize an attached volume while the instance is running), then re-run the update","Check the account's volume size quota and request an increase via the Linode/Akamai console if the requested SizeGB exceeds it","Verify SizeGB is larger than current size (shrinks are rejected by CheckChanges) and within the region maximum (10240 GB)","Confirm the API token has volumes:read_write scope and has not expired","Retry the kops update if the failure was a transient 5xx; the resize is idempotent for an unchanged spec"],"exampleFix":"// before: resize attempted while volume attached to a running instance\nif err := t.Cloud.Client().ResizeVolume(ctx, id, linodego.VolumeResizeOptions{Size: newSize}); err != nil { ... }\n// after: shut down / detach first, or pre-check via instance state\ninst, _ := client.GetInstance(ctx, attachedInstanceID)\nif inst.Status != linodego.InstanceOffline { return fmt.Errorf(\"stop instance %d before resizing volume\", attachedInstanceID) }\nreturn t.Cloud.Client().ResizeVolume(ctx, id, linodego.VolumeResizeOptions{Size: newSize})","handlingStrategy":"validation","validationCode":"// Caller-side guard in cluster spec / before running update:\nfunc validateVolumeResize(current, desired int, attachedInstanceID *int, instanceRunning bool) error {\n    if desired <= current {\n        return fmt.Errorf(\"desired size %d GB must be greater than current %d GB (shrinks unsupported)\", desired, current)\n    }\n    if desired > 10240 {\n        return fmt.Errorf(\"desired size %d GB exceeds Linode volume max of 10240 GB\", desired)\n    }\n    if attachedInstanceID != nil && instanceRunning {\n        return fmt.Errorf(\"volume attached to running instance %d; stop/detach before resizing\", *attachedInstanceID)\n    }\n    return nil\n}","typeGuard":"func isVolumeResizeConflict(err error) bool {\n    var apiErr *linodego.Error\n    if errors.As(err, &apiErr) {\n        return apiErr.Code == 400 && strings.Contains(strings.ToLower(apiErr.Message), \"attach\")\n    }\n    return false\n}","tryCatchPattern":"if err := run(); err != nil {\n    var apiErr *linodego.Error\n    if errors.As(err, &apiErr) && apiErr.Code == 429 {\n        // back off and retry once\n    }\n    return fmt.Errorf(\"volume resize failed: %w\", err)\n}","preventionTips":["Never decrease SizeGB in the cluster spec; only grow","Stop or detach the volume's instance before planned resizes","Track account volume quota in the Linode console before large changes","Keep SizeGB within the 10-10240 GB range","Use a token with volumes:read_write scope and rotate before expiry"],"tags":["linode","storage","resize","api-error","kops"],"backgroundTag":"linode-volume-resize-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}