kubernetes/kops · error
error deleting KeyPair %q: %v
Error message
error deleting KeyPair %q: %v
What it means
DeleteKeypair wraps any error from ec2:DeleteKeyPair into this error naming the keypair ID. Unlike volume/subnet deletion, there is no NotFound special-case here, so deleting an already-removed keypair also surfaces as this error. The raw AWS error is embedded via %v.
Source
Thrown at pkg/resources/aws/aws.go:685
volumes = append(volumes, page.Volumes...)
}
return volumes, nil
}
func DeleteKeypair(cloud fi.Cloud, r *resources.Resource) error {
ctx := context.TODO()
c := cloud.(awsup.AWSCloud)
id := r.ID
klog.V(2).Infof("Deleting EC2 Keypair %q", id)
request := &ec2.DeleteKeyPairInput{
KeyPairId: &id,
}
_, err := c.EC2().DeleteKeyPair(ctx, request)
if err != nil {
return fmt.Errorf("error deleting KeyPair %q: %v", id, err)
}
return nil
}
func ListKeypairs(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) {
ctx := context.TODO()
if !strings.Contains(clusterName, ".") {
klog.Infof("cluster %q is legacy (kube-up) cluster; won't delete keypairs", clusterName)
return nil, nil
}
c := cloud.(awsup.AWSCloud)
keypairName := "kubernetes." + clusterName
klog.V(2).Infof("Listing EC2 Keypairs")
// TODO: We need to match both the name and a prefixView on GitHub (pinned to 4c8573c808)
Solutions
- Check the embedded AWS error code; treat InvalidKeyPair.NotFound as success and skip.
- Verify IAM permissions grant ec2:DeleteKeyPair.
- Retry with backoff if throttled or a transient AWS error occurred.
- Confirm the configured region/account actually contains the keypair ID.
Example fix
// before
if err != nil { return fmt.Errorf("error deleting KeyPair %q: %v", id, err) }
// after
if err != nil {
if awsup.AWSErrorCode(err) == "InvalidKeyPair.NotFound" { return nil }
return fmt.Errorf("error deleting KeyPair %q: %v", id, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
kp, err := ec2Client.DescribeKeyPairs(ctx, &ec2.DescribeKeyPairsInput{KeyPairIds: []string{id}})
if err != nil || len(kp.KeyPairs) == 0 { return nil } // already gone Type guard
func isNotFound(err error) bool { var ae smithy.APIError; return errors.As(err, &ae) && ae.ErrorCode() == "InvalidKeyPair.NotFound" } Try / catch
if err != nil {
if isNotFound(err) { return nil }
if isThrottling(err) { return retryOp() }
return fmt.Errorf("error deleting KeyPair %q: %w", id, err)
} Prevention
- Check keypair existence before deleting to make deletion idempotent.
- Avoid concurrent kops deletes against the same cluster.
- Confirm region/account targeting matches where the keypair lives.
- Grant ec2:DeleteKeyPair in the IAM policy.
When it happens
Trigger: ec2.DeleteKeyPair fails: keypair already deleted (InvalidKeyPair.NotFound), IAM denial (UnauthorizedOperation), throttling, or transient API failure.
Common situations: Re-running cluster deletion after a partial teardown deleted the keypair; IAM policy missing ec2:DeleteKeyPair; concurrent kops runs deleting the same keypair; credential/region mismatch pointing at the wrong account.
Related errors
- error terminating instances: %v
- error listing KeyPairs: %v
- error deleting EgressOnlyInternetGateway %q: %v
- error deleting ec2 LaunchTemplate %q: %v
- error deleting elastic ip %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/7480dd8b4f52d5cc.
Report an issue: GitHub.