{"record":{"id":"3dc67a3cb67e685e","repo":"kubernetes/kops","slug":"error-listing-akamai-linode-instances-w","errorCode":null,"errorMessage":"error listing Akamai (Linode) instances: %w","messagePattern":"error listing Akamai \\(Linode\\) instances: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/linode/resources.go","lineNumber":86,"sourceCode":"\t\tfor _, tracker := range trackers {\n\t\t\tresourceTrackers[tracker.Type+\":\"+tracker.ID] = tracker\n\t\t}\n\t}\n\n\treturn resourceTrackers, nil\n}\n\n// listInstances lists Akamai (Linode) instances owned by the cluster.\nfunc listInstances(cloud fi.Cloud, clusterInfo resources.ClusterInfo) ([]*resources.Resource, error) {\n\tc := cloud.(cloudlinode.LinodeCloud)\n\tlistOptions, err := cloudlinode.ListOptionsForTags(fmt.Sprintf(\"%s:%s\", cloudlinode.TagKubernetesClusterName, clusterInfo.Name))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinstances, err := c.Client().ListInstances(context.Background(), listOptions)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error listing Akamai (Linode) instances: %w\", err)\n\t}\n\n\tvar resourceTrackers []*resources.Resource\n\tfor _, instance := range instances {\n\t\tblocks, err := instanceSubnetBlocks(c, instance)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresourceTrackers = append(resourceTrackers, &resources.Resource{\n\t\t\tName:    instance.Label,\n\t\t\tID:      strconv.Itoa(instance.ID),\n\t\t\tType:    resourceTypeInstance,\n\t\t\tDeleter: deleteInstance,\n\t\t\tBlocks:  blocks,\n\t\t\tObj:     instance,\n\t\t})\n\t}","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/linode/resources.go#L68-L104","documentation":"listInstances in kOps' Akamai (Linode) resource discovery wraps any failure from linodego's ListInstances API call. It means the Linode API rejected or failed the instance list request, so kOps cannot enumerate cluster compute resources.","triggerScenarios":"c.Client().ListInstances(ctx, listOptions) errors: invalid/expired Linode API token, missing account scopes, 429 rate limit, network failure, or a bad ListOptions filter.","commonSituations":"LINODE_TOKEN unset or rotated; token from another account without access to the cluster's region; transient Linode API outage during `kops delete cluster` or get-all.","solutions":["Verify LINODE_TOKEN (or the configured API token) is set, valid, and has sufficient scopes.","Retry after a Linode rate-limit window if the wrapped error is 429.","Check Linode status page / network connectivity for API outages.","Confirm the token belongs to the same Linode account that owns the cluster instances."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: token must be present before calling the API\nif os.Getenv(\"LINODE_TOKEN\") == \"\" {\n    return errors.New(\"LINODE_TOKEN is not set\")\n}","typeGuard":"func isLinodeAuthError(err error) bool {\n    var le linodego.Error\n    if errors.As(err, &le) {\n        return le.Code == 401 || le.Code == 403\n    }\n    return false\n}","tryCatchPattern":"instances, err := c.Client().ListInstances(ctx, listOptions)\nif err != nil {\n    var le linodego.Error\n    if errors.As(err, &le) && le.Code == 429 {\n        return retryWithBackoff(err)\n    }\n    return fmt.Errorf(\"error listing Akamai (Linode) instances: %w\", err)\n}","preventionTips":["Check LINODE_TOKEN validity with `linode-cli profile view` before running kOps operations.","Handle 429 responses with exponential backoff.","Confirm the token's account matches the cluster's Linode account.","Watch the Linode status page during large teardowns."],"tags":["linode","akamai","api-listing","authentication"],"backgroundTag":"cloud-api-list-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"}