{"record":{"id":"3c8c55f76754c67c","repo":"kubernetes/kops","slug":"error-deleting-akamai-linode-vpc-s-s-w","errorCode":null,"errorMessage":"error deleting Akamai (Linode) VPC %s(%s): %w","messagePattern":"error deleting Akamai \\(Linode\\) VPC (.+?)\\((.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/linode/resources.go","lineNumber":305,"sourceCode":"\t\treturn fmt.Errorf(\"error deleting Akamai (Linode) SSH key %s(%s): %w\", tracker.Name, tracker.ID, err)\n\t}\n\n\treturn nil\n}\n\n// deleteVPC deletes an Akamai (Linode) VPC.\nfunc deleteVPC(cloud fi.Cloud, tracker *resources.Resource) error {\n\tc := cloud.(cloudlinode.LinodeCloud)\n\tvpcID, err := parseTrackerIntID(tracker)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := c.Client().DeleteVPC(context.Background(), vpcID); err != nil {\n\t\tif linodego.IsNotFound(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting Akamai (Linode) VPC %s(%s): %w\", tracker.Name, tracker.ID, err)\n\t}\n\n\treturn nil\n}\n\n// deleteSubnet deletes an Akamai (Linode) VPC subnet.\nfunc deleteSubnet(vpcID int, cloud fi.Cloud, tracker *resources.Resource) error {\n\tc := cloud.(cloudlinode.LinodeCloud)\n\tsubnetID, err := parseTrackerIntID(tracker)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := c.Client().DeleteVPCSubnet(context.Background(), vpcID, subnetID); err != nil {\n\t\tif linodego.IsNotFound(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting Akamai (Linode) subnet %s(%s): %w\", tracker.Name, tracker.ID, err)","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/linode/resources.go#L287-L323","documentation":"deleteVPC removes the cluster's Linode VPC. Any DeleteVPC failure other than not-found (which is treated as success) is wrapped with the VPC name and ID. It indicates the Linode API refused or failed the VPC deletion call.","triggerScenarios":"c.Client().DeleteVPC(ctx, vpcID) fails: token lacks write scopes, VPC still has attached resources (subnets/instances/interfaces) preventing deletion, network error, or rate limit.","commonSituations":"Deleting a VPC before its subnets/instances are torn down; using a read-only token during 'kops delete cluster'; orphaned VPC with lingering Linode interfaces attached.","solutions":["Ensure all subnets and instances in the VPC are deleted first (kops does this in dependency order; retry if interrupted)","Use an API token with write access","Retry the delete after partial failures","Remove lingering VPC interfaces via Linode Cloud Manager if needed","Check the wrapped error's HTTP status for the exact cause"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the VPC has no attached resources before deletion\nsubnets, err := c.Client().ListVPCSubnets(ctx, vpcID, nil)\n// also confirm no compute instances remain attached to VPC interfaces","typeGuard":"func isVPCInUse(err error) bool { c := linodego.ErrCode(err); return c == 400 || c == 409 }","tryCatchPattern":"if err := c.Client().DeleteVPC(ctx, vpcID); err != nil {\n\tif linodego.IsNotFound(err) { return nil }\n\tif isVPCInUse(err) { /* delete subnets/instances first, then retry */ }\n\treturn fmt.Errorf(\"error deleting Akamai (Linode) VPC %s(%s): %w\", tracker.Name, tracker.ID, err)\n}","preventionTips":["Always complete instance/subnet teardown before VPC deletion","Use kops' ordered delete rather than manual VPC deletion","Use write-scoped tokens","Re-run kops delete after interrupted runs to finish cleanup"],"tags":["linode","akamai","vpc","delete","api-error"],"backgroundTag":"linode-api-request-failed","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"}