{"record":{"id":"c3f34dc853b1b08c","repo":"kubernetes/kops","slug":"error-listing-akamai-linode-ssh-keys-w-c3f34d","errorCode":null,"errorMessage":"error listing Akamai (Linode) SSH keys: %w","messagePattern":"error listing Akamai \\(Linode\\) SSH keys: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/linodetasks/instance.go","lineNumber":283,"sourceCode":"\tvar keysByName map[string]string\n\n\tfor _, key := range keys {\n\t\tif key == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif key.PublicKey != nil {\n\t\t\tpublicKey, err := fi.ResourceAsString(*key.PublicKey)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error rendering SSH key data: %w\", err)\n\t\t\t}\n\t\t\tauthorizedKeys = append(authorizedKeys, strings.TrimSpace(publicKey))\n\t\t\tcontinue\n\t\t}\n\n\t\tif keysByName == nil {\n\t\t\tlistedKeys, err := client.ListSSHKeys(context.TODO(), nil)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error listing Akamai (Linode) SSH keys: %w\", err)\n\t\t\t}\n\t\t\tkeysByName = make(map[string]string, len(listedKeys))\n\t\t\tfor _, listedKey := range listedKeys {\n\t\t\t\tkeysByName[listedKey.Label] = listedKey.SSHKey\n\t\t\t}\n\t\t}\n\n\t\tpublicKey, found := keysByName[fi.ValueOf(key.Name)]\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"SSH key %q not found in Akamai (Linode)\", fi.ValueOf(key.Name))\n\t\t}\n\t\tauthorizedKeys = append(authorizedKeys, strings.TrimSpace(publicKey))\n\t}\n\n\treturn authorizedKeys, nil\n}\n\n// buildLinodeInterfaces builds the Akamai (Linode) interfaces for the instance based on the subnet ID and whether a public interface is required.","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/linodetasks/instance.go#L265-L301","documentation":"When an authorized key is referenced by name instead of inline content, resolveAuthorizedKeys lazily lists the account's SSH keys via ListSSHKeys to build a label->key map. This wraps any API failure from that listing call.","triggerScenarios":"client.ListSSHKeys fails — bad/expired API token, network error, or Linode API outage — while resolving a name-referenced SSH key during RenderLinode.","commonSituations":"Expired or scope-limited LINODE_TOKEN, connectivity/DNS problems from a CI runner, or a transient Linode API error.","solutions":["Verify the Linode API token is valid and has read access","Check network connectivity to api.linode.com","Retry the apply (transient API errors often resolve)","Alternatively provide the key inline as PublicKey to avoid the lookup"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify token works before applying\nif _, err := client.ListSSHKeys(ctx, nil); err != nil { return fmt.Errorf(\"linode API check failed: %w\", err) }","typeGuard":null,"tryCatchPattern":"listedKeys, err := client.ListSSHKeys(ctx, nil)\nif err != nil {\n    // retry with backoff; abort with wrapped error if persistent\n    return nil, fmt.Errorf(\"error listing Akamai (Linode) SSH keys: %w\", err)\n}","preventionTips":["Refresh LINODE_TOKEN before long CI runs","Ensure the token has account read scopes","Provide keys inline to skip the name lookup path entirely"],"tags":["ssh","linode","api"],"backgroundTag":"cloud-api-list-failure","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"}