thanos-io/thanos · error
list chunk files
Error message
list chunk files
What it means
When lazy-loading a block, bucketBlockSet/bucketBlock lists all chunk objects under <ULID>/chunks/ in the bucket via bkt.Iter. Failure to enumerate the object storage listing is wrapped as "list chunk files" and prevents loading the block.
Solutions
- Verify bucket credentials and that the principal has list permission on the bucket/prefix
- Check object-storage availability and rate limits; add backoff/retry
- Confirm the bucket and block prefix still exist (block may have been deleted/compacted away)
- Inspect the wrapped error for the provider-specific cause (403 vs 5xx vs timeout)
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: ensure list access
it := bkt.Iter(ctx, blockPrefix, func(string) error { return nil }) Try / catch
if err = bkt.Iter(ctx, path.Join(meta.ULID.String(), block.ChunksDirname), func(n string) error {
b.chunkObjs = append(b.chunkObjs, n)
return nil
}); err != nil {
return nil, errors.Wrap(err, "list chunk files")
} Prevention
- Grant list permission on the bucket to the store gateway principal
- Rotate credentials before expiry; monitor auth failures
- Apply backoff/retry on provider rate limits
When it happens
Trigger: The object store Iter call on the block's chunks directory fails: bucket permission revoked, object storage outage, throttling, or misconfigured bucket credentials.
Common situations: Expired cloud credentials or removed IAM list permission; S3/GCS rate limiting under heavy fan-out; temporary object-storage 5xx; bucket deleted or renamed.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/b51ea7a32ccc6f4d.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/store/bucket.go:2500
estimatedMaxChunkSize: maxChunkSize,
}
// Get object handles for all chunk files (segment files) from meta.json, if available.
if len(meta.Thanos.SegmentFiles) > 0 {
b.chunkObjs = make([]string, 0, len(meta.Thanos.SegmentFiles))
for _, sf := range meta.Thanos.SegmentFiles {
b.chunkObjs = append(b.chunkObjs, path.Join(meta.ULID.String(), block.ChunksDirname, sf))
}
return b, nil
}
// Get object handles for all chunk files from storage.
if err = bkt.Iter(ctx, path.Join(meta.ULID.String(), block.ChunksDirname), func(n string) error {
b.chunkObjs = append(b.chunkObjs, n)
return nil
}); err != nil {
return nil, errors.Wrap(err, "list chunk files")
}
return b, nil
}
func (b *bucketBlock) indexFilename() string {
return path.Join(b.meta.ULID.String(), block.IndexFilename)
}
func (b *bucketBlock) readIndexRange(ctx context.Context, off, length int64, logger log.Logger) ([]byte, error) {
r, err := b.bkt.GetRange(ctx, b.indexFilename(), off, length)
if err != nil {
return nil, errors.Wrap(err, "get range reader")
}
defer runutil.CloseWithLogOnErr(logger, r, "readIndexRange close range reader")
// Preallocate the buffer with the exact size so we don't waste allocations
// while progressively growing an initial small buffer. The buffer capacity
// is increased by MinRead to avoid extra allocations due to how ReadFrom()View on GitHub (pinned to 35b8b99117)