Skip to content

fix: ListObjects should return NoSuchBucket for prefix on missing bucket#37

Open
ycjlin wants to merge 1 commit into
pgsty:masterfrom
ycjlin:fix/listobjects-nosuchbucket-prefix
Open

fix: ListObjects should return NoSuchBucket for prefix on missing bucket#37
ycjlin wants to merge 1 commit into
pgsty:masterfrom
ycjlin:fix/listobjects-nosuchbucket-prefix

Conversation

@ycjlin

@ycjlin ycjlin commented Jun 28, 2026

Copy link
Copy Markdown

Community Contribution License

All community contributions in this pull request are licensed to the project maintainers
under the terms of the Apache 2 license.
By creating this pull request I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 license.

Description

ListObjects on a non-existent bucket returned an empty result instead of NoSuchBucket whenever the request hit one of listPath's storage-bypassing shortcuts - most visibly a slash-only prefix such as Prefix="/". AWS S3 returns NoSuchBucket regardless of the prefix/marker/max-keys supplied.

This regressed in 80ca120 ("remove checkBucketExist check entirely to avoid fan-out calls"), which dropped the bucket existence check from checkListObjsArgs. The normal listing path still surfaces a missing bucket via the per-set listing (errVolumeNotFound), but the early-return shortcuts in listPath (slash-only prefix, zero limit, marker outside the prefix) return io.EOF before any set is consulted, masking the missing bucket as an empty listing.

Verify bucket existence (via the existing GetBucketInfo, matching the pattern already used by ListMultipartUploads) only on those shortcut paths, so the hot listing path keeps avoiding the fan-out.

Motivation and Context

Fixes #32

How to test this PR?

Just run the tests

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Optimization (provides speedup with no functional changes)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • Fixes a regression (80ca120)
  • Unit tests added/updated
  • Internal documentation updated
  • Create a documentation update request here

ListObjects on a non-existent bucket returned an empty result instead of
NoSuchBucket whenever the request hit one of listPath's storage-bypassing
shortcuts - most visibly a slash-only prefix such as Prefix="/". AWS S3
returns NoSuchBucket regardless of the prefix/marker/max-keys supplied.

This regressed in 80ca120 ("remove checkBucketExist check entirely to
avoid fan-out calls"), which dropped the bucket existence check from
checkListObjsArgs. The normal listing path still surfaces a missing bucket
via the per-set listing (errVolumeNotFound), but the early-return shortcuts
in listPath (slash-only prefix, zero limit, marker outside the prefix)
return io.EOF before any set is consulted, masking the missing bucket as an
empty listing.

Verify bucket existence (via the existing GetBucketInfo, matching the
pattern already used by ListMultipartUploads) only on those shortcut paths,
so the hot listing path keeps avoiding the fan-out.

Fixes pgsty#32

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ycjlin

ycjlin commented Jun 29, 2026

Copy link
Copy Markdown
Author

Thanks @cbornet for the prompt review.
cc: @Vonng for merging.

@Vonng

Vonng commented Jun 30, 2026

Copy link
Copy Markdown
Member

Thanks for the PR. I looked into the history behind this behavior.

The relevant upstream change is 80ca12008 / minio#18917, which removed the unconditional checkBucketExist call from several object API argument checks. The motivation was performance: GetBucketInfo() can fan out across peers and becomes costly on large distributed deployments, especially with 100+ nodes.

Because of that, I am concerned about reintroducing bucket existence checks too broadly. Moving the check back into the generic ListObjects argument path would effectively undo the upstream optimization and could bring back the same scalability issue.

This PR is much narrower than a full revert, but it is still a user-visible behavior change: some ListObjects calls against a non-existent bucket would change from an empty result to NoSuchBucket. Given that this fork is intended to stay close to upstream and is mainly maintained for binary supply-chain/security purposes, my current preference is to keep this behavior aligned with upstream for non-security fixes.

@cbornet

cbornet commented Jul 7, 2026

Copy link
Copy Markdown

I understand your concern but:

  • returning a NoSuchBucket is more correct.
  • the change from 80ca12008 was already a user-visible change. We would just re-establish it to the behavior it used to have. In my case I want to upgrade from a version prior to the 80ca12008 and I can't do it precisely because of that behavior change.
  • The definition of silo/minio is MinIO is a Kubernetes-native S3-compatible object storage solution and S3 returns NoSuchBucket. A lot of (most?) people use Minio as a S3 simulation during unit/integration tests so having the same behavior as S3 is very important.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

listObjects should return NoSuchBucket when the bucket doesn't exist and prefix is passed

3 participants