kubernetes/kops · error

error parsing Akamai (Linode) %s ID %q: %w

Error message

error parsing Akamai (Linode) %s ID %q: %w

What it means

parseTrackerIntID in kOps' Akamai (Linode) resource listing converts the tracker's string ID to an int (Linode resource IDs are numeric). If strconv.Atoi fails, this error wraps the parse failure, naming the resource type and the offending ID string. It propagates out of every Linode delete function (deleteSSHKey, deleteVPC, deleteSubnet, deleteInstance, deleteVolume).

Source

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

	"k8s.io/kops/upup/pkg/fi"
	cloudlinode "k8s.io/kops/upup/pkg/fi/cloudup/linode"
)

type listFn func(fi.Cloud, resources.ClusterInfo) ([]*resources.Resource, error)

const (
	resourceTypeVPC      = "vpc"
	resourceTypeSubnet   = "subnet"
	resourceTypeSSHKey   = "ssh-key"
	resourceTypeInstance = "instance"
	resourceTypeVolume   = "volume"
)

// parseTrackerIntID parses the tracker's string ID into an integer, which is used for Akamai (Linode) resource IDs.
func parseTrackerIntID(tracker *resources.Resource) (int, error) {
	id, err := strconv.Atoi(tracker.ID)
	if err != nil {
		return 0, fmt.Errorf("error parsing Akamai (Linode) %s ID %q: %w", tracker.Type, tracker.ID, err)
	}
	return id, nil
}

// ListResources collects Akamai (Linode) cloud resources owned by the cluster.
func ListResources(cloud cloudlinode.LinodeCloud, clusterInfo resources.ClusterInfo) (map[string]*resources.Resource, error) {
	resourceTrackers := make(map[string]*resources.Resource)

	listFunctions := []listFn{
		listVPCs,
		listSubnets,
		listInstances,
		listVolumes,
		listSSHKeys,
	}

	for _, fn := range listFunctions {
		trackers, err := fn(cloud, clusterInfo)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the tracker ID in the error message and in the kOps state store; replace any non-numeric ID with the correct numeric Linode ID.
  2. Find the real ID with `linode-cli sshkeys list` / `linode-cli vpcs list` etc., and correct the state entry.
  3. If the resource no longer exists, remove the stale tracker from the state store so kOps stops trying to delete it.
  4. Upgrade/downgrade kOps if a version change changed the ID format written to state.

Example fix

// before: tracker.ID is a label
id, err := strconv.Atoi(tracker.ID) // "my-cluster-vpc" -> error
// after: validate before use
id, err := strconv.Atoi(strings.TrimSpace(tracker.ID))
if err != nil {
    return 0, fmt.Errorf("error parsing Akamai (Linode) %s ID %q: %w", tracker.Type, tracker.ID, err)
}
// caller-side: only create trackers with fmt.Sprintf("%d", numericID)
Defensive patterns

Strategy: validation

Validate before calling

func validLinodeID(id string) bool {
    _, err := strconv.Atoi(strings.TrimSpace(id))
    return err == nil
}
// call before invoking any delete: if !validLinodeID(tracker.ID) { fix state store entry first }

Type guard

func isIDParseError(err error) bool {
    var numErr *strconv.NumError
    return errors.As(err, &numErr)
}

Try / catch

id, err := parseTrackerIntID(tracker)
if err != nil {
    var numErr *strconv.NumError
    if errors.As(err, &numErr) {
        log.Printf("skipping malformed tracker ID %q for %s; clean up manually", tracker.ID, tracker.Type)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: tracker.ID is not a plain decimal integer: empty string, whitespace, a Linode label instead of an ID, or a corrupted/edited kOps state store entry.

Common situations: Manually edited cluster state in the kOps state store; a resource tracker populated with a label like "my-ssh-key" instead of the numeric Linode ID; older kOps version wrote a different ID format than the current code expects.

Related errors


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