{"record":{"id":"179e5dca73bc0777","repo":"flipped-aurora/gin-vue-admin","slug":"function-client-listobjectsv2-failed-err","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/aws_s3.go","lineNumber":188,"sourceCode":"\t}\n\tbucket := global.GVA_CONFIG.AwsS3.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":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/aws_s3.go#L170-L206","documentation":"ListFiles in the AWS S3 upload adapter wraps any error returned by the AWS SDK's ListObjectsV2 API call into this generic message. It means the S3 ListObjectsV2 request itself failed — the SDK got a transport, auth, permission, or service-side rejection before any listing results could be processed. The original AWS error text is appended verbatim after 'err:'.","triggerScenarios":"Calling ListFiles(ctx, prefix, cursor, limit) on the aws_s3 uploader when: credentials are invalid/expired, the IAM identity lacks s3:ListBucket on the bucket, the bucket name/region are wrong, a custom endpoint is unreachable, or the network to S3 is down. The caller-supplied cursor is passed as ContinuationToken, and an invalid/expired cursor also makes the call fail.","commonSituations":"Wrong AWS_REGION for the bucket (SignatureDoesNotMatch/IllegalLocationConstraint), IAM policy missing s3:ListBucket (AccessDenied), non-existent bucket name, stale pagination cursor passed after bucket contents changed, misconfigured custom endpoint for MinIO/on-prem S3, VPC without internet/endpoint access.","solutions":["Read the appended err text: if AccessDenied, grant s3:ListBucket on the bucket to the configured AccessKey's IAM identity","Verify server config: Bucket, Region/Endpoint, AccessKey, SecretKey are correct for the target S3-compatible service","If triggered by a bad cursor, restart pagination with an empty cursor and return fresh ContinuationToken to clients instead of reusing stale ones","Check network reachability (DNS, proxy, VPC endpoint) from the server to the S3 endpoint","Enable AWS SDK debug logging to capture the HTTP status and request ID from the failed call"],"exampleFix":"// before\ncursor := oldCursorFromClient // possibly stale\nfiles, next, hasMore, err := uploader.ListFiles(ctx, prefix, cursor, 100)\n// after\nif cursor == \"stale-signature\" { // detect S3 error text mentioning ContinuationToken\n    files, next, hasMore, err = uploader.ListFiles(ctx, prefix, \"\", 100)\n}","handlingStrategy":"try-catch","validationCode":"if uploader == nil || cfg.Bucket == \"\" || cfg.AccessKey == \"\" || cfg.SecretKey == \"\" {\n    return errors.New(\"s3 uploader not configured\")\n}","typeGuard":"func isAWSErr(err error) awserr.Error { var e awserr.Error; return errors.As(err, &e) }","tryCatchPattern":"files, next, hasMore, err := uploader.ListFiles(ctx, prefix, cursor, 100)\nif err != nil {\n    logger.Error(\"ListFiles failed\", zap.Error(err))\n    if strings.Contains(err.Error(), \"ContinuationToken\") {\n        files, next, hasMore, err = uploader.ListFiles(ctx, prefix, \"\", 100)\n    }\n    if err != nil { return err }\n}","preventionTips":["Grant s3:ListBucket to the service account and verify with aws CLI before deploying","Validate bucket/region/endpoint config at startup with a smoke ListObjectsV2 call","Never expose or persist pagination cursors beyond their validity; restart on stale-cursor errors","Monitor the appended err text per error code and alert on AccessDenied"],"tags":["aws","s3","storage","network"],"backgroundTag":"s3-list-objects-access-denied","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}