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

  1. Resolve the DependencyViolation: list and delete remaining ENIs, NAT gateways, and instances in the subnet, then retry.
  2. Wait a few minutes — AWS dependency cleanup is sometimes asynchronous — then retry.
  3. Check whether the subnet is shared (RAM) and must be deleted by the owner account.
  4. 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

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


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