Tencent/WeKnora · error

failed to upload file to OSS (multipart): %w

Error message

failed to upload file to OSS (multipart): %w

What it means

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.

Source

Thrown at internal/application/service/file/oss.go:200

	// Use Uploader for files > 10MB (auto multipart with concurrent uploads)
	const multipartThreshold = 10 * 1024 * 1024
	if file.Size > multipartThreshold {
		uploader := s.client.NewUploader(func(uo *oss.UploaderOptions) {
			uo.PartSize = 10 * 1024 * 1024 // 10MB per part
			uo.ParallelNum = 3             // 3 concurrent uploads
		})

		_, err = uploader.UploadFrom(ctx,
			&oss.PutObjectRequest{
				Bucket:      oss.Ptr(s.bucketName),
				Key:         oss.Ptr(objectName),
				ContentType: oss.Ptr(contentType),
			},
			src,
		)
		if err != nil {
			return "", fmt.Errorf("failed to upload file to OSS (multipart): %w", err)
		}
	} else {
		_, err = s.client.PutObject(ctx, &oss.PutObjectRequest{
			Bucket:      oss.Ptr(s.bucketName),
			Key:         oss.Ptr(objectName),
			Body:        src,
			ContentType: oss.Ptr(contentType),
		})
		if err != nil {
			return "", fmt.Errorf("failed to upload file to OSS: %w", err)
		}
	}

	return fmt.Sprintf("oss://%s/%s", s.bucketName, objectName), nil
}

// SaveBytes saves bytes data to OSS.
// If temp is true and temp bucket is configured, saves to temp bucket.

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the wrapped error with %v/errors.Unwrap to identify the OSS error code (AccessDenied, NoSuchBucket, RequestTimeout).
  2. Verify OSS credentials (AccessKey ID/Secret, STS token) are valid and not expired.
  3. Confirm the bucket exists and the RAM role has oss:PutObject/oss:AbortMultipartUpload permissions.
  4. Check network connectivity from the host to the configured OSS endpoint (region mismatch is common).
  5. Retry the upload; multipart uploads can be resumed and aborted parts cleaned up.

Example fix

// before
if err != nil {
    return "", fmt.Errorf("failed to upload file to OSS (multipart): %w", err)
}
// after
if err != nil {
    var ossErr oss.GoError
    if errors.As(err, &ossErr) {
        logger.Errorf(ctx, "OSS multipart upload failed: code=%v", ossErr)
    }
    return "", fmt.Errorf("failed to upload file to OSS (multipart): %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// before upload
if src == nil { return errors.New("nil source for SaveFile") }
// ensure credentials/bucket configured
if s.bucketName == "" || s.client == nil { return errors.New("OSS not configured") }

Try / catch

path, err := svc.SaveFile(ctx, src, tenantID, name, ctype, temp)
var ossErr *oss.ServiceError
switch {
case err == nil:
    // ok
case errors.As(err, &ossErr):
    // inspect ossErr.Code: AccessDenied -> fix IAM; NoSuchBucket -> fix config
case errors.As(err, &netErr) || isTransient(err):
    // retry with exponential backoff
default:
    return fmt.Errorf("save failed: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/5fb6252a08a0db7f. Report an issue: GitHub.