Tencent/WeKnora · error · ErrCrossBackendCopy
oss copy rejected source %q: %w
Error message
oss copy rejected source %q: %w
What it means
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.
Source
Thrown at internal/application/service/file/oss.go:258
Body: bytes.NewReader(data),
ContentType: oss.Ptr(utils.GetContentTypeByExt(ext)),
})
if err != nil {
return "", fmt.Errorf("failed to upload bytes to OSS: %w", err)
}
return fmt.Sprintf("oss://%s/%s", targetBucket, objectName), nil
}
// CopyFile copies an existing OSS object to a new knowledge-owned object using a
// server-side CopyObject (no data leaves OSS). The destination uses the same
// layout as SaveFile. Returns ErrCrossBackendCopy when srcPath is not an oss:// path.
func (s *ossFileService) CopyFile(ctx context.Context,
srcPath string, tenantID uint64, knowledgeID string,
) (string, error) {
srcBucket, srcKey, err := parseOssFilePath(srcPath)
if err != nil {
return "", fmt.Errorf("oss copy rejected source %q: %w", srcPath, ErrCrossBackendCopy)
}
if err := utils.SafeObjectKey(srcKey); err != nil {
return "", fmt.Errorf("invalid source path: %w", err)
}
ext := filepath.Ext(srcPath)
destKey := fmt.Sprintf("%s%d/%s/%s%s", s.pathPrefix, tenantID, knowledgeID, uuid.New().String(), ext)
_, err = s.client.CopyObject(ctx, &oss.CopyObjectRequest{
Bucket: oss.Ptr(s.bucketName),
Key: oss.Ptr(destKey),
SourceBucket: oss.Ptr(srcBucket),
SourceKey: oss.Ptr(srcKey),
})
if err != nil {
return "", fmt.Errorf("failed to copy file in OSS: %w", err)
}
View on GitHub (pinned to 988cbb0330)
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.
Example fix
// before
newPath, err := ossSvc.CopyFile(ctx, srcPath, tenantID, knowledgeID)
// after
if !strings.HasPrefix(srcPath, "oss://") {
return ErrCrossBackendCopy
}
newPath, err := ossSvc.CopyFile(ctx, srcPath, tenantID, knowledgeID) Defensive patterns
Strategy: validation
Validate before calling
// before calling CopyFile
if !strings.HasPrefix(srcPath, "oss://") {
return fmt.Errorf("%w: not an oss path: %s", ErrCrossBackendCopy, srcPath)
} Type guard
func isOSSPath(p string) bool { return strings.HasPrefix(p, "oss://") } Try / catch
newPath, err := svc.CopyFile(ctx, srcPath, tenantID, knowledgeID)
if errors.Is(err, ErrCrossBackendCopy) {
// route to the backend matching srcPath's scheme instead
} Prevention
- 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.
When it happens
Trigger: 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'.
Common situations: 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.
Related errors
- invalid source path: %w
- obs copy rejected source %q: %w
- invalid file name: %w
- failed to copy file in OSS: %w
- invalid file path: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/0cfe7c2a88c19eb1.
Report an issue: GitHub.