JuliusBrussee/caveman · error
objectstore: list
Error message
objectstore: list %q: %w
What it means
minioStore.List wraps obj.Err produced while iterating ListObjects with the given prefix (recursive). The listing stream is lazy; errors arrive mid-iteration as per-entry errors, so a partially built keys slice is discarded and the prefix plus cause are wrapped with %w.
Solutions
- Unwrap and check minio.ErrorResponse for AccessDenied (grant s3:ListBucket) or SlowDown (backoff).
- Retry the whole List on transient errors; results are recomputed from scratch.
- Use ListPage with bounded maxKeys to reduce per-call work on huge prefixes.
- Check network stability/timeout configuration for long listings.
- Avoid extremely broad prefixes; narrow them to reduce pagination.
Example fix
// before
keys, err := store.List(ctx, "") // lists entire bucket
// after
keys, err := store.List(ctx, "uploads/2026/09/") // narrow prefix, fewer pages
if err != nil {
return fmt.Errorf("list uploads: %w", err)
} Defensive patterns
Strategy: retry
Try / catch
keys, err := store.List(ctx, prefix)
if err != nil {
var mr minio.ErrorResponse
if errors.As(err, &mr) && mr.Code == "SlowDown" {
time.Sleep(backoff.Next())
keys, err = store.List(ctx, prefix)
}
if err != nil { return err }
} Prevention
- Use narrow, structured prefixes instead of listing whole buckets.
- Throttle concurrent List calls to avoid SlowDown.
- Prefer ListPage for large prefixes to bound each request.
- Grant s3:ListBucket to service accounts that enumerate objects.
When it happens
Trigger: Calling List(ctx, prefix) when the recursive listing fails partway: AccessDenied on s3:ListBucket, connection drop during pagination, SlowDown throttling, or invalid prefix causing backend errors.
Common situations: Large prefixes that require many paginated LIST calls over unstable networks; IAM missing list permission; heavy concurrent listing triggering rate limits; S3-compatible backends with pagination quirks.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- objectstore: list page
- objectstore: list versions
- objectstore: delete
- objectstore: delete version
- objectstore: read
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/d6d2aad22dbf78a8.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/objectstore/objectstore.go:360
return nil
}
func (m *minioStore) Exists(ctx context.Context, key string) (bool, error) {
_, err := m.client.StatObject(ctx, m.bucket, key, minio.StatObjectOptions{})
if err != nil {
if minio.ToErrorResponse(err).Code == "NoSuchKey" {
return false, nil
}
return false, fmt.Errorf("objectstore: stat %q: %w", key, err)
}
return true, nil
}
func (m *minioStore) List(ctx context.Context, prefix string) ([]string, error) {
var keys []string
for obj := range m.client.ListObjects(ctx, m.bucket, minio.ListObjectsOptions{Prefix: prefix, Recursive: true}) {
if obj.Err != nil {
return nil, fmt.Errorf("objectstore: list %q: %w", prefix, obj.Err)
}
keys = append(keys, obj.Key)
}
return keys, nil
}
func (m *minioStore) ListPage(ctx context.Context, prefix, startAfter string, maxKeys int) (ObjectPage, error) {
if maxKeys <= 0 {
return ObjectPage{}, fmt.Errorf("objectstore: page size must be positive")
}
// Request one extra key so the caller can tell whether another page exists,
// while cancelling the producer as soon as the bounded result is known.
pageCtx, cancel := context.WithCancel(ctx)
defer cancel()
keys := make([]string, 0, maxKeys)
var extra string
for obj := range m.client.ListObjects(pageCtx, m.bucket, minio.ListObjectsOptions{
Prefix: prefix, Recursive: true, StartAfter: startAfter, MaxKeys: maxKeys + 1,View on GitHub (pinned to 3ee70a1026)