flipped-aurora/gin-vue-admin · error
function client.ListObjectsV2() failed, err:
Error message
function client.ListObjectsV2() failed, err:
What it means
CloudflareR2.ListFiles calls ListObjectsV2 against the R2 endpoint; any SDK error from that call is wrapped in this message. The listing request was rejected before results could be read; the caller-supplied cursor is passed as ContinuationToken and can itself invalidate the call.
Source
Thrown at server/utils/upload/cloudflare_r2.go:173
}
bucket := global.GVA_CONFIG.CloudflareR2.Bucket
if limit <= 0 {
limit = 100
}
input := &s3.ListObjectsV2Input{
Bucket: aws.String(bucket),
Prefix: aws.String(prefix),
MaxKeys: aws.Int32(int32(limit)),
}
if cursor != "" {
input.ContinuationToken = aws.String(cursor)
}
out, err := client.ListObjectsV2(ctx, input)
if err != nil {
return nil, "", false, errors.New("function client.ListObjectsV2() failed, err:" + err.Error())
}
for _, obj := range out.Contents {
fi := FileInfo{}
if obj.Key != nil {
fi.Key = *obj.Key
}
if obj.Size != nil {
fi.Size = *obj.Size
}
if obj.LastModified != nil {
fi.LastModified = *obj.LastModified
}
files = append(files, fi)
}
if out.NextContinuationToken != nil {
nextCursor = *out.NextContinuationTokenView on GitHub (pinned to 3136500ef3)
Solutions
- Verify endpoint includes your Cloudflare account ID and Bucket matches the R2 bucket name exactly
- Check token permissions (Object Read) and that AccessKey/SecretAccessKey are current
- If the cursor is stale, restart listing from empty cursor and expose only fresh nextCursor values to clients
- Read the wrapped err text: AccessDenied vs. InvalidToken vs. network timeout point to different fixes
- Confirm egress/firewall allows HTTPS to <account>.r2.cloudflarestorage.com
Example fix
// before files, next, _, err := r2.ListFiles(ctx, prefix, cursorFromHoursAgo, 100) // after files, next, _, err := r2.ListFiles(ctx, prefix, "", 100) // fresh pagination
Defensive patterns
Strategy: try-catch
Validate before calling
if cfg.Endpoint == "" || !strings.Contains(cfg.Endpoint, "r2.cloudflarestorage.com") || cfg.Bucket == "" {
return errors.New("R2 list config incomplete")
} Type guard
null
Try / catch
files, next, hasMore, err := r2.ListFiles(ctx, prefix, cursor, 100)
if err != nil {
logger.Error("R2 ListFiles failed", zap.Error(err))
if strings.Contains(err.Error(), "token") || strings.Contains(err.Error(), "Denied") {
return fmt.Errorf("check R2 credentials/permissions: %w", err)
}
if cursor != "" {
return r2.ListFiles(ctx, prefix, "", 100) // stale cursor fallback
}
return err
} Prevention
- Validate endpoint (with account ID) and bucket at startup via a probe listing
- Use fresh cursors only; don't persist ContinuationTokens long-term
- Grant the R2 token object read permission and rotate it safely
- Monitor R2 status/egress connectivity from your network
When it happens
Trigger: ListFiles(ctx, prefix, cursor, limit) when credentials/token are invalid or lack read permission, endpoint/bucket misconfigured, network to R2 fails, or the ContinuationToken from a previous page is expired/invalid (R2 tokens are short-lived).
Common situations: Wrong R2 endpoint (missing account ID), token rotated but old creds in config, reusing a cursor from a different bucket/prefix or after long delay, R2 outage, VPC egress blocked.
Related errors
- function client.DeleteObject() failed, err:
- function client.DeleteObjects() failed, err:
- function client.ListObjectsV2() failed, err:
- function file.Open() failed, err:
- unknown error
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/226a2be3d15d997c.
Report an issue: GitHub.