kubernetes/kops · error
error deleting Subnet %q: %v
Error message
error deleting Subnet %q: %v
What it means
DeleteSubnet wraps DeleteSubnet API failures in this error, except InvalidSubnetID.NotFound (treated as already-deleted) and dependency violations returned as-is via IsDependencyViolation. It means AWS refused subnet deletion for a real subnet, most commonly because resources still exist in it.
Source
Thrown at pkg/resources/aws/aws.go:750
func DeleteSubnet(cloud fi.Cloud, tracker *resources.Resource) error {
ctx := context.TODO()
c := cloud.(awsup.AWSCloud)
id := tracker.ID
klog.V(2).Infof("Deleting EC2 Subnet %q", id)
request := &ec2.DeleteSubnetInput{
SubnetId: &id,
}
_, err := c.EC2().DeleteSubnet(ctx, request)
if err != nil {
if awsup.AWSErrorCode(err) == "InvalidSubnetID.NotFound" {
klog.V(2).Infof("Got InvalidSubnetID.NotFound error deleting subnet %q; will treat as already-deleted", id)
return nil
} else if IsDependencyViolation(err) {
return err
}
return fmt.Errorf("error deleting Subnet %q: %v", id, err)
}
return nil
}
func ListSubnets(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) {
ctx := context.TODO()
c := cloud.(awsup.AWSCloud)
subnets, err := DescribeSubnets(cloud)
if err != nil {
return nil, fmt.Errorf("error listing subnets: %v", err)
}
var resourceTrackers []*resources.Resource
elasticIPs := sets.NewString()
ownedElasticIPs := sets.NewString()
natGatewayIds := sets.NewString()
ownedNatGatewayIds := sets.NewString()
for _, subnet := range subnets {View on GitHub (pinned to 4c8573c808)
Solutions
- Resolve the DependencyViolation: list and delete remaining ENIs, NAT gateways, and instances in the subnet, then retry.
- Wait a few minutes — AWS dependency cleanup is sometimes asynchronous — then retry.
- Check whether the subnet is shared (RAM) and must be deleted by the owner account.
- Verify IAM allows ec2:DeleteSubnet; retry with backoff if throttled.
Example fix
// before
return fmt.Errorf("error deleting Subnet %q: %v", id, err)
// after
if awsup.AWSErrorCode(err) == "DependencyViolation" {
klog.V(2).Infof("subnet %q has dependencies; cleaning up ENIs before retry", id)
CleanupSubnetENIs(cloud, id)
return RetryDeleteSubnet(cloud, id)
}
return fmt.Errorf("error deleting Subnet %q: %v", id, err) Defensive patterns
Strategy: retry
Validate before calling
enis, _ := ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{Filters: []types.Filter{awsup.NewEC2Filter("subnet-id", id)}})
if len(enis.NetworkInterfaces) > 0 { return fmt.Errorf("subnet %s still has %d ENIs", id, len(enis.NetworkInterfaces)) } Type guard
func isDependencyViolationErr(err error) bool { var ae smithy.APIError; return errors.As(err, &ae) && ae.ErrorCode() == "DependencyViolation" } Try / catch
err := DeleteSubnet(cloud, id)
if isDependencyViolationErr(err) {
cleanupSubnetResources(cloud, id)
time.Sleep(30 * time.Second)
return DeleteSubnet(cloud, id)
} Prevention
- Tear down dependent resources (NLBs, NAT GWs, instances) before subnets.
- Sweep leftover ENIs — LoadBalancer-created ENIs are the most common blocker.
- Retry subnet deletion after a delay; AWS dependency cleanup can lag.
- Check for RAM-shared subnets owned by another account.
When it happens
Trigger: ec2.DeleteSubnet fails with errors like DependencyViolation (ENIs, NAT gateways, or instances still in the subnet), UnauthorizedOperation, or throttling — while InvalidSubnetID.NotFound is filtered out beforehand.
Common situations: Deleting a cluster whose subnets still contain leftover ENIs (LBs, lambda VPC attachments); orphaned NAT gateways; deleting a subnet shared from another account; IAM denials.
Related errors
- error listing subnets: %v
- error detaching InternetGateway %q: %v
- VPC ID is required when EgressOnlyInternetGateway is shared
- EgressOnlyInternetGateway for shared VPC was not found
- error creating EgressOnlyInternetGateway: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9a0842fa81062491.
Report an issue: GitHub.