Tencent/WeKnora · error

failed to upload file to OSS: %w

Error message

failed to upload file to OSS: %w

What it means

This error is returned by ossFileService.SaveFile when the simple (single-request) PutObject call to Alibaba Cloud OSS fails. It wraps the SDK error so callers can inspect the root cause. It is the non-multipart branch of SaveFile, used for smaller files or when the caller's reader fits a single request.

Source

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

			&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.
// Otherwise saves to main bucket.
func (s *ossFileService) SaveBytes(ctx context.Context, data []byte, tenantID uint64, fileName string, temp bool) (string, error) {
	safeName, err := utils.SafeFileName(fileName)
	if err != nil {
		return "", fmt.Errorf("invalid file name: %w", err)
	}
	ext := filepath.Ext(safeName)

	targetBucket := s.bucketName
	client := s.client

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Unwrap the error to read the OSS error code (e.g., AccessDenied, NoSuchBucket, SignatureDoesNotMatch).
  2. Validate s.bucketName and endpoint configuration match the actual bucket region.
  3. Verify RAM policy grants oss:PutObject on the target key prefix.
  4. Confirm credentials/STS tokens are current.
  5. Check that src is readable and not already consumed (a drained reader causes body errors).

Example fix

// before
_, err = s.client.PutObject(ctx, &oss.PutObjectRequest{...})
if err != nil {
    return "", fmt.Errorf("failed to upload file to OSS: %w", err)
}
// after
if err != nil {
    logger.Errorf(ctx, "OSS PutObject failed bucket=%s key=%s: %v", s.bucketName, objectName, err)
    return "", fmt.Errorf("failed to upload file to OSS: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if s.bucketName == "" { return errors.New("OSS bucket not configured") }
if fi, err := os.Stat(localPath); err != nil || fi.Size() == 0 { return fmt.Errorf("source unreadable: %w", err) }

Try / catch

path, err := svc.SaveFile(ctx, src, tenantID, name, ctype, false)
var svcErr *oss.ServiceError
if errors.As(err, &svcErr) {
    switch svcErr.Code {
    case "AccessDenied": // fix RAM permissions
    case "NoSuchBucket": // fix bucket config
    case "SignatureDoesNotMatch": // fix credentials
    }
}

Prevention

When it happens

Trigger: Calling SaveFile with content under the multipart threshold and client.PutObject fails: invalid credentials, bucket does not exist, no PutObject permission, request body read error from src, or network failure before/during the PUT.

Common situations: Misconfigured bucket name in config/env; OSS endpoint region mismatch (bucket in cn-hangzhou, client pointed at another region); antivirus/permission tools locking the source file; SDK credentials expired (signature-time errors).

Related errors


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