{"record":{"id":"0cfe7c2a88c19eb1","repo":"Tencent/WeKnora","slug":"oss-copy-rejected-source-q-w","errorCode":null,"errorMessage":"oss copy rejected source %q: %w","messagePattern":"oss copy rejected source %q: %w","errorType":"validation","errorClass":"ErrCrossBackendCopy","httpStatus":null,"severity":"error","filePath":"internal/application/service/file/oss.go","lineNumber":258,"sourceCode":"\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}\n\n\text := filepath.Ext(srcPath)\n\tdestKey := fmt.Sprintf(\"%s%d/%s/%s%s\", s.pathPrefix, tenantID, knowledgeID, uuid.New().String(), ext)\n\n\t_, err = s.client.CopyObject(ctx, &oss.CopyObjectRequest{\n\t\tBucket:       oss.Ptr(s.bucketName),\n\t\tKey:          oss.Ptr(destKey),\n\t\tSourceBucket: oss.Ptr(srcBucket),\n\t\tSourceKey:    oss.Ptr(srcKey),\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to copy file in OSS: %w\", err)\n\t}\n","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/oss.go#L240-L276","documentation":"This error is returned by ossFileService.CopyFile when the srcPath is not a valid oss:// URL, i.e., parseOssFilePath fails. The service wraps it together with the sentinel error ErrCrossBackendCopy to signal that this backend cannot handle the given source path. Callers should route the file to the matching backend service instead of forcing a copy through the OSS implementation.","triggerScenarios":"Calling CopyFile with srcPath that lacks the oss:// scheme prefix (e.g., s3://bucket/key, /local/path/file, or an empty string), so parseOssFilePath returns 'invalid OSS file path'.","commonSituations":"Multi-backend deployments where a file was originally stored in S3/MinIO/COS but the OSS service is invoked generically; refactors that dropped the scheme prefix; DB rows storing legacy absolute paths instead of backend URIs.","solutions":["Check srcPath starts with oss:// before calling CopyFile.","If ErrCrossBackendCopy is returned, dispatch to the file service matching the path's scheme instead.","Fix data sources that persist legacy paths without the backend scheme.","Normalize stored file paths to scheme-qualified URIs at write time."],"exampleFix":"// before\nnewPath, err := ossSvc.CopyFile(ctx, srcPath, tenantID, knowledgeID)\n// after\nif !strings.HasPrefix(srcPath, \"oss://\") {\n    return ErrCrossBackendCopy\n}\nnewPath, err := ossSvc.CopyFile(ctx, srcPath, tenantID, knowledgeID)","handlingStrategy":"validation","validationCode":"// before calling CopyFile\nif !strings.HasPrefix(srcPath, \"oss://\") {\n    return fmt.Errorf(\"%w: not an oss path: %s\", ErrCrossBackendCopy, srcPath)\n}","typeGuard":"func isOSSPath(p string) bool { return strings.HasPrefix(p, \"oss://\") }","tryCatchPattern":"newPath, err := svc.CopyFile(ctx, srcPath, tenantID, knowledgeID)\nif errors.Is(err, ErrCrossBackendCopy) {\n    // route to the backend matching srcPath's scheme instead\n}","preventionTips":["Always store file paths as scheme-qualified URIs (oss://bucket/key).","Dispatch copy/get/delete through a router that selects the backend by URI scheme.","Validate scheme at API boundaries before invoking a specific backend service.","Migrate legacy absolute paths in the DB to scheme-qualified paths."],"tags":["oss","copy","validation","path-parsing"],"backgroundTag":"cross-backend-copy","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}