{"record":{"id":"5fb6252a08a0db7f","repo":"Tencent/WeKnora","slug":"failed-to-upload-file-to-oss-multipart-w","errorCode":null,"errorMessage":"failed to upload file to OSS (multipart): %w","messagePattern":"failed to upload file to OSS \\(multipart\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/oss.go","lineNumber":200,"sourceCode":"\n\t// Use Uploader for files > 10MB (auto multipart with concurrent uploads)\n\tconst multipartThreshold = 10 * 1024 * 1024\n\tif file.Size > multipartThreshold {\n\t\tuploader := s.client.NewUploader(func(uo *oss.UploaderOptions) {\n\t\t\tuo.PartSize = 10 * 1024 * 1024 // 10MB per part\n\t\t\tuo.ParallelNum = 3             // 3 concurrent uploads\n\t\t})\n\n\t\t_, err = uploader.UploadFrom(ctx,\n\t\t\t&oss.PutObjectRequest{\n\t\t\t\tBucket:      oss.Ptr(s.bucketName),\n\t\t\t\tKey:         oss.Ptr(objectName),\n\t\t\t\tContentType: oss.Ptr(contentType),\n\t\t\t},\n\t\t\tsrc,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to upload file to OSS (multipart): %w\", err)\n\t\t}\n\t} else {\n\t\t_, err = s.client.PutObject(ctx, &oss.PutObjectRequest{\n\t\t\tBucket:      oss.Ptr(s.bucketName),\n\t\t\tKey:         oss.Ptr(objectName),\n\t\t\tBody:        src,\n\t\t\tContentType: oss.Ptr(contentType),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to upload file to OSS: %w\", err)\n\t\t}\n\t}\n\n\treturn fmt.Sprintf(\"oss://%s/%s\", s.bucketName, objectName), nil\n}\n\n// SaveBytes saves bytes data to OSS.\n// If temp is true and temp bucket is configured, saves to temp bucket.","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/oss.go#L182-L218","documentation":"This error is returned by ossFileService.SaveFile when the multipart (InitiateMultipartUpload-style) upload of a file stream to Alibaba Cloud OSS fails via the aliyun oss v2 Go SDK. It wraps the underlying SDK error, so the original cause (network, credentials, permissions, size limits) is available via errors.Unwrap or errors.As. The service intentionally distinguishes the multipart path from the simple PutObject path to aid debugging.","triggerScenarios":"Calling SaveFile with a src that exceeds the multipart threshold, and the underlying client.UploadFrom / multipart call fails: expired or missing OSS credentials, network interruption mid-upload, bucket not existing or lacking oss:PutObject permission, or an aborted part upload exceeding limits.","commonSituations":"Deployments with stale AccessKey/Secret after key rotation; VPC/network egress blocked from the pod to the OSS endpoint; IAM/RAM policy changes removing write access to the bucket; files larger than the simple-upload threshold hitting the multipart path for the first time.","solutions":["Inspect the wrapped error with %v/errors.Unwrap to identify the OSS error code (AccessDenied, NoSuchBucket, RequestTimeout).","Verify OSS credentials (AccessKey ID/Secret, STS token) are valid and not expired.","Confirm the bucket exists and the RAM role has oss:PutObject/oss:AbortMultipartUpload permissions.","Check network connectivity from the host to the configured OSS endpoint (region mismatch is common).","Retry the upload; multipart uploads can be resumed and aborted parts cleaned up."],"exampleFix":"// before\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to upload file to OSS (multipart): %w\", err)\n}\n// after\nif err != nil {\n    var ossErr oss.GoError\n    if errors.As(err, &ossErr) {\n        logger.Errorf(ctx, \"OSS multipart upload failed: code=%v\", ossErr)\n    }\n    return \"\", fmt.Errorf(\"failed to upload file to OSS (multipart): %w\", err)\n}","handlingStrategy":"retry","validationCode":"// before upload\nif src == nil { return errors.New(\"nil source for SaveFile\") }\n// ensure credentials/bucket configured\nif s.bucketName == \"\" || s.client == nil { return errors.New(\"OSS not configured\") }","typeGuard":null,"tryCatchPattern":"path, err := svc.SaveFile(ctx, src, tenantID, name, ctype, temp)\nvar ossErr *oss.ServiceError\nswitch {\ncase err == nil:\n    // ok\ncase errors.As(err, &ossErr):\n    // inspect ossErr.Code: AccessDenied -> fix IAM; NoSuchBucket -> fix config\ncase errors.As(err, &netErr) || isTransient(err):\n    // retry with exponential backoff\ndefault:\n    return fmt.Errorf(\"save failed: %w\", err)\n}","preventionTips":["Verify OSS credentials and STS token expiry before long-running upload jobs.","Grant oss:PutObject and oss:AbortMultipartUpload on the target prefix in RAM policy.","Confirm the endpoint region matches the bucket region in config.","Monitor multipart upload abort/cleanup to avoid orphaned parts and quota issues.","Add transient-error retry with backoff around SaveFile."],"tags":["oss","upload","multipart","alibaba-cloud","network"],"backgroundTag":"oss-upload-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}