kubernetes/kops · error

error deleting ENI %q: %v

Error message

error deleting ENI %q: %v

What it means

kOps wraps the AWS SDK error from ec2.DeleteNetworkInterface in DeleteENI. DependencyViolation errors are returned unmodified (so the resource tracker can retry later), NoSuchEntity is treated as already deleted, and anything else is wrapped with this message. It means the ENI could not be deleted for a reason other than a pending dependency or prior deletion.

Source

Thrown at pkg/resources/aws/eni.go:53

	c := cloud.(awsup.AWSCloud)

	id := r.ID

	klog.V(2).Infof("Deleting EC2 ENI %q", id)
	request := &ec2.DeleteNetworkInterfaceInput{
		NetworkInterfaceId: &id,
	}
	_, err := c.EC2().DeleteNetworkInterface(ctx, request)
	if err != nil {
		if awsup.AWSErrorCode(err) == "InvalidNetworkInterfaceID.NotFound" {
			// Concurrently deleted
			return nil
		}

		if IsDependencyViolation(err) {
			return err
		}
		return fmt.Errorf("error deleting ENI %q: %v", id, err)
	}
	return nil
}

func DumpENI(op *resources.DumpOperation, r *resources.Resource) error {
	data := make(map[string]interface{})
	data["id"] = r.ID
	data["type"] = ec2types.ResourceTypeNetworkInterface
	data["raw"] = r.Obj

	op.Dump.Resources = append(op.Dump.Resources, data)

	return nil
}

func DescribeENIs(cloud fi.Cloud, vpcID, clusterName string) (map[string]ec2types.NetworkInterface, error) {
	if vpcID == "" {
		return nil, nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped error's code; if AccessDenied, grant ec2:DeleteNetworkInterface
  2. Re-run the delete — kOps retries DependencyViolation cases automatically and treats missing ENIs as success
  3. Check `aws ec2 describe-network-interfaces --network-interface-ids <id>` for its attachment status
  4. If throttled, retry after backoff
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm ENI exists and is available before delete
out, err := ec2Client.DescribeNetworkInterfaces(ctx, &ec2.DescribeNetworkInterfacesInput{NetworkInterfaceIds: []string{id}})
if err == nil && len(out.NetworkInterfaces) > 0 && out.NetworkInterfaces[0].Status == "available" { /* safe to delete */ }

Type guard

func isDependencyViolation(err error) bool {
  return awsup.AWSErrorCode(err) == "DependencyViolation" || strings.Contains(err.Error(), "DependencyViolation")
}

Try / catch

err := DeleteENI(ctx, cloud, eniID)
switch {
case awsup.AWSErrorCode(err) == "InvalidNetworkInterfaceID.NotFound": // already deleted, ok
case isDependencyViolation(err): // schedule retry later
default: return err
}

Prevention

When it happens

Trigger: DeleteNetworkInterface returns an unexpected error: AccessDenied on ec2:DeleteNetworkInterface, AuthFailure/InvalidNetworkInterface.ID.NotFound variants not matched by the pre-checks, throttling, or request serialization failures.

Common situations: IAM policy restricting deletion to specific ENI ARNs; EC2 API throttling during large cluster teardown; ENI attached to a resource that keeps returning errors other than DependencyViolation (e.g. service-linked state).

Related errors


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