{"record":{"id":"e0f40e7503aac1cc","repo":"cloudreve/cloudreve","slug":"failed-to-get-uploaded-file-size-w","errorCode":null,"errorMessage":"failed to get uploaded file size: %w","messagePattern":"failed to get uploaded file size: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/filemanager/driver/cos/cos.go","lineNumber":558,"sourceCode":"\t\tChunkSize:   handler.chunkSize,\n\t}, nil\n}\n\n// 取消上传凭证\nfunc (handler *Driver) CancelToken(ctx context.Context, uploadSession *fs.UploadSession) error {\n\t_, err := handler.client.Object.AbortMultipartUpload(ctx, uploadSession.Props.SavePath, uploadSession.UploadID)\n\treturn err\n}\n\nfunc (handler *Driver) CompleteUpload(ctx context.Context, session *fs.UploadSession) error {\n\tif session.SentinelTaskID == 0 {\n\t\treturn nil\n\t}\n\n\t// Make sure uploaded file size is correct\n\tres, err := handler.client.Object.Head(ctx, session.Props.SavePath, &cossdk.ObjectHeadOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get uploaded file size: %w\", err)\n\t}\n\n\tif res.ContentLength != session.Props.Size {\n\t\treturn serializer.NewError(\n\t\t\tserializer.CodeMetaMismatch,\n\t\t\tfmt.Sprintf(\"File size not match, expected: %d, actual: %d\", session.Props.Size, res.ContentLength),\n\t\t\tnil,\n\t\t)\n\t}\n\treturn nil\n}\n\nfunc (handler *Driver) Capabilities() *driver.Capabilities {\n\tmediaMetaExts := handler.policy.Settings.MediaMetaExts\n\tif !handler.policy.Settings.NativeMediaProcessing {\n\t\tmediaMetaExts = nil\n\t}\n\treturn &driver.Capabilities{","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/cloudreve/cloudreve/blob/20c95ad73f3a8bcb72887fea91ff31ab24fa1011/pkg/filemanager/driver/cos/cos.go#L540-L576","documentation":"During CompleteUpload, the HEAD request used to verify the uploaded object's size failed outright (distinct from the size-mismatch error that follows a successful HEAD). The wrapped cause is usually a 404 (object not present at session SavePath), 403 (no HeadObject right), or a network failure at completion time.","triggerScenarios":"Client uploaded parts to a different key/bucket than session.Props.SavePath; the object was deleted between upload finish and completion; credentials lacking cos:GetObject; a proxy stripping HEAD requests; transient cross-region consistency delay.","commonSituations":"Browser/CORS direct-upload flows where the frontend SDK normalizes the key differently (leading slash, encoding) than the server's SavePath; reverse proxies blocking HEAD; policies switched right before completion.","solutions":["Confirm the key the client actually uploaded to matches session.Props.SavePath byte-for-byte (leading slashes, URL encoding)","Unwrap the error to distinguish 404 (wrong key/absent), 403 (permissions), and transport failures","Ensure the CAM policy allows GetObject (HEAD) on the bucket","Retry CompleteUpload after a short delay; HEAD is idempotent and transient 404s from eventual consistency resolve"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := driver.CompleteUpload(ctx, session)\nif err != nil && strings.Contains(err.Error(), \"failed to get uploaded file size\") {\n    // HEAD at completion can fail transiently; CompleteUpload is idempotent for this driver\n    time.Sleep(2 * time.Second)\n    err = driver.CompleteUpload(ctx, session)\n}","preventionTips":["Ensure the client uploads to exactly session.Props.SavePath (same leading slash and encoding)","Keep cos:GetObject (HEAD) permission in the policy","Do not delete or move the object between upload completion and session completion"],"tags":["cos","tencent-cloud","upload","head-request","eventual-consistency","storage"],"backgroundTag":null,"analyzedSha":"20c95ad73f3a8bcb72887fea91ff31ab24fa1011","analyzedAt":"2026-08-16T01:42:55.403Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}