kubernetes/kops · error

error deleting Volume %q: %v

Error message

error deleting Volume %q: %v

What it means

DeleteVolume wraps any error from the EC2 DeleteVolume API call (other than InvalidVolume.NotFound, which is treated as already-deleted) into a formatted error identifying the volume ID. It propagates dependency violations unchanged via IsDependencyViolation so callers can retry. This error means the AWS API rejected the volume deletion for a reason other than 'volume does not exist'.

Source

Thrown at pkg/resources/aws/aws.go:570

	ctx := context.TODO()
	c := cloud.(awsup.AWSCloud)

	id := r.ID

	klog.V(2).Infof("Deleting EC2 Volume %q", id)
	request := &ec2.DeleteVolumeInput{
		VolumeId: &id,
	}
	_, err := c.EC2().DeleteVolume(ctx, request)
	if err != nil {
		if awsup.AWSErrorCode(err) == "InvalidVolume.NotFound" {
			klog.V(2).Infof("Got InvalidVolume.NotFound error deleting Volume %q; will treat as already-deleted", id)
			return nil
		}
		if IsDependencyViolation(err) {
			return err
		}
		return fmt.Errorf("error deleting Volume %q: %v", id, err)
	}
	return nil
}

func ListVolumes(cloud fi.Cloud, vpcID, clusterName string) ([]*resources.Resource, error) {
	ctx := context.TODO()
	c := cloud.(awsup.AWSCloud)

	volumes, err := DescribeVolumes(cloud)
	if err != nil {
		return nil, err
	}
	var resourceTrackers []*resources.Resource

	elasticIPs := make(map[string]bool)
	for _, volume := range volumes {
		id := aws.ToString(volume.VolumeId)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Detach the volume from its instance first (or wait for the instance to terminate), then retry the delete.
  2. Wait until the volume leaves a transitional state (creating/deleting) before retrying.
  3. Check IAM permissions for ec2:DeleteVolume on the volume/CMK, and fix the policy.
  4. Retry after backoff if the cause is throttling or a transient AWS error.

Example fix

// before
err := DeleteVolume(cloud, id)
if err != nil { return err }
// after
vol, _ := FindVolume(cloud, id)
for _, a := range vol.Attachments { DetachVolume(cloud, *a.VolumeId) }
WaitUntilVolumeAvailable(cloud, id)
err := DeleteVolume(cloud, id)
Defensive patterns

Strategy: retry

Validate before calling

vol, err := ec2Client.DescribeVolumes(ctx, &ec2.DescribeVolumesInput{VolumeIds: []string{id}})
if err != nil || len(vol.Volumes) == 0 { return nil }
for _, a := range vol.Volumes[0].Attachments {
  if aws.ToString(a.State) != "detached" { return fmt.Errorf("volume %s still attached", id) }
}

Type guard

func isDependencyViolation(err error) bool { var ae smithy.APIError; return errors.As(err, &ae) && ae.ErrorCode() == "VolumeInUse" }

Try / catch

err := DeleteVolume(cloud, id)
var ae smithy.APIError
if errors.As(err, &ae) && ae.ErrorCode() == "VolumeInUse" {
  // detach then retry with backoff
} else if err != nil {
  return err
}

Prevention

When it happens

Trigger: EC2 DeleteVolume returns an error for a real volume ID: the volume is attached to an instance, is in a transitional state (creating/deleting), is encrypted with a key the caller cannot use, or a transient AWS/throttling failure occurs.

Common situations: Cluster teardown racing with instance termination that still has the EBS volume attached; deleting a volume that is in 'creating' state; IAM policies denying ec2:DeleteVolume; EC2 API throttling during large deletions.

Related errors


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