{"record":{"id":"79106b056a12eb9d","repo":"flipped-aurora/gin-vue-admin","slug":"cos-delete-s-failed-code-s-message-s","errorCode":null,"errorMessage":"cos delete %s failed: code=%s, message=%s","messagePattern":"cos delete (.+?) failed: code=(.+?), message=(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/upload/tencent_cos.go","lineNumber":88,"sourceCode":"\tobjects := make([]cos.Object, 0, len(keys))\n\tfor _, k := range keys {\n\t\tobjects = append(objects, cos.Object{Key: global.GVA_CONFIG.TencentCOS.PathPrefix + \"/\" + k})\n\t}\n\n\tres, _, err := client.Object.DeleteMulti(ctx, &cos.ObjectDeleteMultiOptions{\n\t\tObjects: objects,\n\t\tQuiet:   true,\n\t})\n\tif err != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(err).Error(\"function client.Object.DeleteMulti() failed\")\n\t\treturn nil, errors.New(\"function client.Object.DeleteMulti() failed, err:\" + err.Error())\n\t}\n\n\tif res != nil {\n\t\tfor _, e := range res.Errors {\n\t\t\tfailed = append(failed, DeleteFailure{\n\t\t\t\tKey: e.Key,\n\t\t\t\tErr: fmt.Errorf(\"cos delete %s failed: code=%s, message=%s\", e.Key, e.Code, e.Message),\n\t\t\t})\n\t\t}\n\t}\n\treturn failed, nil\n}\n\n// ListFiles 按前缀列举对象，marker 分页：Marker=cursor，NextMarker→nextCursor，IsTruncated→hasMore。\nfunc (*TencentCOS) ListFiles(ctx context.Context, prefix, cursor string, limit int) (files []FileInfo, nextCursor string, hasMore bool, err error) {\n\tif limit <= 0 {\n\t\tlimit = 100\n\t}\n\n\tclient := NewClient()\n\tres, _, err := client.Bucket.Get(ctx, &cos.BucketGetOptions{\n\t\tPrefix:  prefix,\n\t\tMarker:  cursor,\n\t\tMaxKeys: limit,\n\t})","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/tencent_cos.go#L70-L106","documentation":"The Tencent COS DeleteFiles implementation issues a multi-delete and inspects res.Errors for per-object failures, wrapping each as \"cos delete %s failed: code=%s, message=%s\" with the COS error code and message. The overall request can succeed while individual key deletions fail, and this surfaces those partial failures.","triggerScenarios":"Calling DeleteFiles on the tencent_cos uploader when res.Errors is non-empty — e.g. AccessDenied on a key, keys that no longer exist, or invalid key names rejected by COS.","commonSituations":"CAM policy lacking cos:DeleteObject for the bucket; objects already deleted by lifecycle rules; malformed keys (leading slash, invalid characters) in the batch request.","solutions":["Inspect code= and message= on each DeleteFailure to identify the COS error and affected key.","Grant the secret's CAM role cos:DeleteObject permission on the bucket.","Normalize key names (strip leading '/', validate characters) before batch delete.","Retry only failed keys; treat AlreadyDeleted responses as success if idempotency is needed."],"exampleFix":"// before\nfailed, _ := uploader.DeleteFiles(ctx, keys)\n\n// after\nfailed, err := uploader.DeleteFiles(ctx, keys)\nfor _, f := range failed {\n    log.Printf(\"cos delete retry for %s: %v\", f.Key, f.Err)\n}","handlingStrategy":"try-catch","validationCode":"for _, key := range keys {\n    if strings.HasPrefix(key, \"/\") {\n        return fmt.Errorf(\"COS keys must not start with '/': %q\", key)\n    }\n}","typeGuard":null,"tryCatchPattern":"failed, err := uploader.DeleteFiles(ctx, keys)\nif err != nil {\n    return err\n}\nfor _, f := range failed {\n    log.Printf(\"cos delete failed key=%s: %v\", f.Key, f.Err)\n    // parse code= to distinguish AccessDenied vs NoSuchKey\n}","preventionTips":["Ensure the CAM role has cos:DeleteObject on the bucket","Normalize keys (trim leading slashes) before batch delete","Always inspect the failed list — COS batch delete is partial-capable","Enable bucket audit logs to trace denied deletes"],"tags":["cos","tencent-cloud","object-storage","delete"],"backgroundTag":"object-delete-failed","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}