What is wrong:Client.ListObjects and ListObjectsStream (internal/s3/client.go) use the SDK paginator, which ends silently when a page has IsTruncated=true but no NextContinuationToken; a server that answers V2 listings V1-style does that. prune then counts only the manifests on the first page and treats the blobs of the remaining snapshots as unreferenced (collectReferencedBlobs, internal/vaultik/prune.go).
How it was shown: a throwaway test in internal/storage put gofakes3 behind a handler that pages by 2 and removes NextContinuationToken, then stored 5 keys: List returned 2 of 5 keys and no error, and the same for ListStream.
Definition of done
A page marked truncated without a continuation token is an error from List and ListStream, so prune, snapshot list and remote nuke take their existing path for a destination that cannot be listed, and prune deletes nothing.
A test covers the cut-short listing for both methods.
Model: opus-5-5
Found by the defect hunt in https://git.eeqj.de/sneak/vaultik/issues/288 (part 5).
**What is wrong:** `Client.ListObjects` and `ListObjectsStream` (`internal/s3/client.go`) use the SDK paginator, which ends silently when a page has `IsTruncated=true` but no `NextContinuationToken`; a server that answers V2 listings V1-style does that. `prune` then counts only the manifests on the first page and treats the blobs of the remaining snapshots as unreferenced (`collectReferencedBlobs`, `internal/vaultik/prune.go`).
**How it was shown:** a throwaway test in `internal/storage` put gofakes3 behind a handler that pages by 2 and removes `NextContinuationToken`, then stored 5 keys: `List` returned 2 of 5 keys and no error, and the same for `ListStream`.
**Definition of done**
- A page marked truncated without a continuation token is an error from `List` and `ListStream`, so `prune`, `snapshot list` and `remote nuke` take their existing path for a destination that cannot be listed, and `prune` deletes nothing.
- A test covers the cut-short listing for both methods.
Model: opus-5-5
Implemented in #333: ListObjects and ListObjectsStream now return ErrNoContinuationToken for a page marked truncated with no continuation token, so List and ListStream fail on it and their callers take their existing path for a destination that cannot be listed. A new test in internal/storage/s3_test.go covers both methods.
Model: opus-5-5
Implemented in https://git.eeqj.de/sneak/vaultik/pulls/333: `ListObjects` and `ListObjectsStream` now return `ErrNoContinuationToken` for a page marked truncated with no continuation token, so `List` and `ListStream` fail on it and their callers take their existing path for a destination that cannot be listed. A new test in `internal/storage/s3_test.go` covers both methods.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by the defect hunt in #288 (part 5).
What is wrong:
Client.ListObjectsandListObjectsStream(internal/s3/client.go) use the SDK paginator, which ends silently when a page hasIsTruncated=truebut noNextContinuationToken; a server that answers V2 listings V1-style does that.prunethen counts only the manifests on the first page and treats the blobs of the remaining snapshots as unreferenced (collectReferencedBlobs,internal/vaultik/prune.go).How it was shown: a throwaway test in
internal/storageput gofakes3 behind a handler that pages by 2 and removesNextContinuationToken, then stored 5 keys:Listreturned 2 of 5 keys and no error, and the same forListStream.Definition of done
ListandListStream, soprune,snapshot listandremote nuketake their existing path for a destination that cannot be listed, andprunedeletes nothing.Model: opus-5-5
Implemented in #333:
ListObjectsandListObjectsStreamnow returnErrNoContinuationTokenfor a page marked truncated with no continuation token, soListandListStreamfail on it and their callers take their existing path for a destination that cannot be listed. A new test ininternal/storage/s3_test.gocovers both methods.Model: opus-5-5