{"record":{"id":"7e73166b4bb765ec","repo":"Tencent/WeKnora","slug":"failed-to-upload-bytes-to-oss-w","errorCode":null,"errorMessage":"failed to upload bytes to OSS: %w","messagePattern":"failed to upload bytes to OSS: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/oss.go","lineNumber":244,"sourceCode":"\n\ttargetBucket := s.bucketName\n\tclient := s.client\n\tobjectName := fmt.Sprintf(\"%s%d/exports/%s%s\", s.pathPrefix, tenantID, uuid.New().String(), ext)\n\n\tif temp && s.tempClient != nil {\n\t\ttargetBucket = s.tempBucketName\n\t\tclient = s.tempClient\n\t\tobjectName = fmt.Sprintf(\"exports/%d/%s%s\", tenantID, uuid.New().String(), ext)\n\t}\n\n\t_, err = client.PutObject(ctx, &oss.PutObjectRequest{\n\t\tBucket:      oss.Ptr(targetBucket),\n\t\tKey:         oss.Ptr(objectName),\n\t\tBody:        bytes.NewReader(data),\n\t\tContentType: oss.Ptr(utils.GetContentTypeByExt(ext)),\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to upload bytes to OSS: %w\", err)\n\t}\n\n\treturn fmt.Sprintf(\"oss://%s/%s\", targetBucket, objectName), nil\n}\n\n// CopyFile copies an existing OSS object to a new knowledge-owned object using a\n// server-side CopyObject (no data leaves OSS). The destination uses the same\n// layout as SaveFile. Returns ErrCrossBackendCopy when srcPath is not an oss:// path.\nfunc (s *ossFileService) CopyFile(ctx context.Context,\n\tsrcPath string, tenantID uint64, knowledgeID string,\n) (string, error) {\n\tsrcBucket, srcKey, err := parseOssFilePath(srcPath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"oss copy rejected source %q: %w\", srcPath, ErrCrossBackendCopy)\n\t}\n\tif err := utils.SafeObjectKey(srcKey); err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid source path: %w\", err)\n\t}","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/oss.go#L226-L262","documentation":"This error is returned by ossFileService.SaveBytes when the PutObject call uploading the byte slice to OSS fails. It wraps the SDK error, so the OSS-level cause (auth, permissions, network, quota) is preserved. The content type is derived from the file extension via utils.GetContentTypeByExt before upload.","triggerScenarios":"Calling SaveBytes with valid data but client.PutObject fails: expired credentials, missing oss:PutObject on the target bucket (main or temp bucket), network failure, bucket missing, or payload exceeding OSS/SDK size limits for a single PUT.","commonSituations":"Temp-bucket misconfiguration (SaveBytes with temp=true targeting a nonexistent temp bucket); oversized in-memory exports exceeding single-PUT limits; key rotation invalidating credentials mid-run; egress firewall rules blocking OSS endpoints.","solutions":["Unwrap the error to identify the OSS error code.","Verify target bucket (main vs temp bucket when temp=true) exists and credentials have write access.","Check network/endpoint configuration for the region the bucket lives in.","For very large payloads, reduce size or add multipart support / compression before upload.","Retry transient failures (RequestTimeout, 5xx) with backoff."],"exampleFix":"// before\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to upload bytes to OSS: %w\", err)\n}\n// after\nif err != nil {\n    var retriable bool\n    var netErr net.Error\n    if errors.As(err, &netErr) { retriable = true }\n    return \"\", fmt.Errorf(\"failed to upload bytes to OSS (retriable=%v): %w\", retriable, err)\n}","handlingStrategy":"retry","validationCode":"// pre-checks before SaveBytes\nif len(data) == 0 { return errors.New(\"empty payload\") }\nif temp && tempBucketName == \"\" { return errors.New(\"temp bucket not configured\") }","typeGuard":null,"tryCatchPattern":"path, err := svc.SaveBytes(ctx, data, tenantID, name, temp)\nvar svcErr *oss.ServiceError\nif errors.As(err, &svcErr) {\n    if isRetryableCode(svcErr.Code) { // RequestTimeout, InternalError, 5xx\n        // retry with backoff\n    }\n}","preventionTips":["Verify both main and temp bucket configuration when temp=true is used.","Check RAM write permissions on the target bucket prefix.","Keep single-PUT payloads within limits; compress or chunk very large exports.","Retry transient network/5xx failures with exponential backoff.","Confirm credentials are valid for the lifetime of batch export jobs."],"tags":["oss","upload","putobject","bytes","alibaba-cloud"],"backgroundTag":"oss-upload-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}