{"record":{"id":"226a2be3d15d997c","repo":"flipped-aurora/gin-vue-admin","slug":"function-client-listobjectsv2-failed-err-226a2b","errorCode":null,"errorMessage":"function client.ListObjectsV2() failed, err:","messagePattern":"function client\\.ListObjectsV2\\(\\) failed, err:","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/upload/cloudflare_r2.go","lineNumber":173,"sourceCode":"\t}\n\tbucket := global.GVA_CONFIG.CloudflareR2.Bucket\n\n\tif limit <= 0 {\n\t\tlimit = 100\n\t}\n\n\tinput := &s3.ListObjectsV2Input{\n\t\tBucket:  aws.String(bucket),\n\t\tPrefix:  aws.String(prefix),\n\t\tMaxKeys: aws.Int32(int32(limit)),\n\t}\n\tif cursor != \"\" {\n\t\tinput.ContinuationToken = aws.String(cursor)\n\t}\n\n\tout, err := client.ListObjectsV2(ctx, input)\n\tif err != nil {\n\t\treturn nil, \"\", false, errors.New(\"function client.ListObjectsV2() failed, err:\" + err.Error())\n\t}\n\n\tfor _, obj := range out.Contents {\n\t\tfi := FileInfo{}\n\t\tif obj.Key != nil {\n\t\t\tfi.Key = *obj.Key\n\t\t}\n\t\tif obj.Size != nil {\n\t\t\tfi.Size = *obj.Size\n\t\t}\n\t\tif obj.LastModified != nil {\n\t\t\tfi.LastModified = *obj.LastModified\n\t\t}\n\t\tfiles = append(files, fi)\n\t}\n\n\tif out.NextContinuationToken != nil {\n\t\tnextCursor = *out.NextContinuationToken","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/cloudflare_r2.go#L155-L191","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nfiles, next, _, err := r2.ListFiles(ctx, prefix, cursorFromHoursAgo, 100)\n// after\nfiles, next, _, err := r2.ListFiles(ctx, prefix, \"\", 100) // fresh pagination","handlingStrategy":"try-catch","validationCode":"if cfg.Endpoint == \"\" || !strings.Contains(cfg.Endpoint, \"r2.cloudflarestorage.com\") || cfg.Bucket == \"\" {\n    return errors.New(\"R2 list config incomplete\")\n}","typeGuard":"null","tryCatchPattern":"files, next, hasMore, err := r2.ListFiles(ctx, prefix, cursor, 100)\nif err != nil {\n    logger.Error(\"R2 ListFiles failed\", zap.Error(err))\n    if strings.Contains(err.Error(), \"token\") || strings.Contains(err.Error(), \"Denied\") {\n        return fmt.Errorf(\"check R2 credentials/permissions: %w\", err)\n    }\n    if cursor != \"\" {\n        return r2.ListFiles(ctx, prefix, \"\", 100) // stale cursor fallback\n    }\n    return err\n}","preventionTips":["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"],"tags":["cloudflare-r2","s3","list","storage"],"backgroundTag":"s3-list-objects-access-denied","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}