kubernetes/kops · error

error listing Akamai (Linode) SSH keys: %w

Error message

error listing Akamai (Linode) SSH keys: %w

What it means

listSSHKeys in the kOps Linode (Akamai) resource cleanup code enumerates all SSH keys registered with the Linode account via linodego's ListSSHKeys. If that API call fails, the error is wrapped with this message and returned so cluster deletion aborts. It means the Linode API rejected or could not serve the SSH key listing request.

Source

Thrown at pkg/resources/linode/resources.go:200

		if vpc.Label != vpcLabel {
			continue
		}
		if region != "" && vpc.Region != region {
			continue
		}

		clusterVPCs = append(clusterVPCs, vpc)
	}

	return clusterVPCs, nil
}

// listSSHKeys lists Akamai (Linode) SSH keys that were generated for the cluster.
func listSSHKeys(cloud fi.Cloud, clusterInfo resources.ClusterInfo) ([]*resources.Resource, error) {
	c := cloud.(cloudlinode.LinodeCloud)
	keys, err := c.Client().ListSSHKeys(context.Background(), nil)
	if err != nil {
		return nil, fmt.Errorf("error listing Akamai (Linode) SSH keys: %w", err)
	}

	keyLabelPrefix := cloudlinode.NormalizeLinodeLabel("kubernetes."+clusterInfo.Name) + "-"
	var resourceTrackers []*resources.Resource
	for _, key := range keys {
		if !strings.HasPrefix(key.Label, keyLabelPrefix) {
			continue
		}

		resourceTrackers = append(resourceTrackers, &resources.Resource{
			Name:    key.Label,
			ID:      strconv.Itoa(key.ID),
			Type:    resourceTypeSSHKey,
			Deleter: deleteSSHKey,
			Obj:     key,
		})
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the Linode API token (LINODE_TOKEN) is valid, unexpired, and has read scopes
  2. Test connectivity to https://api.linode.com/v4/profile from the host
  3. Re-run the delete command after transient API errors; the operation is idempotent
  4. Check Linode status page for API incidents
  5. Enable linodego debug logging to inspect the raw HTTP response

Example fix

// before
keys, err := c.Client().ListSSHKeys(context.Background(), nil)
if err != nil {
	return nil, fmt.Errorf("error listing Akamai (Linode) SSH keys: %w", err)
}
// after
keys, err := c.Client().ListSSHKeys(context.Background(), nil)
if err != nil {
	if linodego.ErrCode(err) == 401 {
		return nil, fmt.Errorf("error listing Akamai (Linode) SSH keys: check LINODE_TOKEN credentials: %w", err)
	}
	return nil, fmt.Errorf("error listing Akamai (Linode) SSH keys: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check credentials before running kops delete
curl -sS -H "Authorization: Bearer $LINODE_TOKEN" https://api.linode.com/v4/profile | jq .username

Type guard

func isLinodeAuthError(err error) bool { return linodego.ErrCode(err) == 401 || linodego.ErrCode(err) == 403 }

Try / catch

keys, err := c.Client().ListSSHKeys(context.Background(), nil)
if err != nil {
	if isLinodeAuthError(err) { /* fix token, then retry */ }
	return fmt.Errorf("error listing Akamai (Linode) SSH keys: %w", err)
}

Prevention

When it happens

Trigger: linodego ListSSHKeys returns a non-nil error: invalid or expired API token, network failure, Linode API 4xx/5xx response, or rate limiting during 'kops delete cluster' discovery of cluster resources.

Common situations: Expired LINODE_TOKEN with insufficient scopes, corporate proxy/firewall blocking api.linode.com, Linode API outage or 429 rate limit while deleting many resources, wrong API endpoint configured.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0235d19b547cae1e. Report an issue: GitHub.