AWS
S3 Bucket
Cloud Storage
Troubleshooting
Empty Bucket

Can't Delete Empty S3 Bucket

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

An S3 bucket can look empty in the console and still refuse deletion. In almost every case, the bucket is not truly empty from S3's point of view, or the caller lacks the exact permissions needed to remove the remaining hidden state.

Why an "Empty" Bucket Still Fails Deletion

S3 requires the bucket to be completely empty before deletion. That includes more than ordinary visible objects.

Common blockers are:

  • old object versions in a versioned bucket
  • delete markers left behind by versioning
  • in-progress multipart uploads
  • Object Lock or legal hold settings
  • insufficient IAM or bucket-policy permissions

The console's top-level object view does not always make those details obvious.

Check Versioning First

If versioning was ever enabled, deleting the current visible objects is not enough. Old versions and delete markers still count.

Use the AWS CLI to inspect versions:

bash
aws s3api list-object-versions --bucket my-bucket

If that returns any Versions or DeleteMarkers, the bucket is not empty yet.

You must remove them explicitly:

bash
1aws s3api delete-object \
2  --bucket my-bucket \
3  --key path/to/file.txt \
4  --version-id 3HL4kqtJlcpXroDTDmjVBH40Nrjfkd

This is the most common reason people cannot delete an "empty" bucket.

Check Multipart Uploads

Incomplete multipart uploads also block cleanup. These uploads do not appear like normal objects in standard listings.

List them with:

bash
aws s3api list-multipart-uploads --bucket my-bucket

Abort any remaining upload:

bash
1aws s3api abort-multipart-upload \
2  --bucket my-bucket \
3  --key large-file.bin \
4  --upload-id AbCdEf1234567890

Until those uploads are aborted, the bucket is not fully removable.

Permissions Can Look Like an Emptiness Problem

Sometimes the bucket really is empty, but your identity does not have the right permissions. Deleting a bucket usually needs s3:DeleteBucket, and cleanup may also require permissions for listing versions, deleting objects, or aborting multipart uploads.

So if cleanup commands fail with access denied errors, the issue is authorization, not bucket state.

Automating Full Cleanup with the CLI

For a non-versioned bucket, recursive delete is often enough:

bash
aws s3 rm s3://my-bucket --recursive

But for versioned buckets, you need to remove versions and delete markers too. Many teams use a short script or lifecycle cleanup for this in operations workflows, but the core point is that recursive remove alone does not erase historical versions.

Less Common Blockers

Object Lock and retention settings can prevent deletion even when you know exactly which object remains. If the bucket is used for compliance or retention-sensitive data, check whether those protections are enabled before assuming you made a tooling mistake.

Replication and lifecycle transitions can also leave you waiting on state changes, though versioning and multipart uploads are far more common causes.

Common Pitfalls

The biggest pitfall is trusting the main console object list as proof that the bucket is empty. It is not sufficient for versioned buckets.

Another issue is deleting the current object version but leaving delete markers or older versions behind. S3 still sees bucket contents.

Developers also sometimes run aws s3 rm --recursive and assume the job is complete. That command is helpful, but it does not clean up the full version history by itself.

Finally, do not treat every deletion failure as an IAM problem. Many of them are real hidden-content problems, especially in long-lived buckets.

Summary

  • An S3 bucket must be completely empty before it can be deleted.
  • Versioned buckets require deleting object versions and delete markers, not just visible files.
  • In-progress multipart uploads can also block deletion.
  • Check IAM permissions if cleanup commands fail with access errors.
  • The fastest diagnostic commands are list-object-versions and list-multipart-uploads.

Course illustration
Course illustration

All Rights Reserved.