Tencent/WeKnora · error

MinerU Cloud file upload: %w

Error message

MinerU Cloud file upload: %w

What it means

After obtaining an upload URL, Read uploads the raw document bytes with uploadFile; any failure is wrapped as "MinerU Cloud file upload: %w". The presigned-URL PUT/POST to the storage backend failed, so the batch never gets processable content.

Source

Thrown at internal/infrastructure/docparser/mineru_cloud_converter.go:85

	ext := filepath.Ext(req.FileName)
	if ext == "" && req.FileType != "" {
		ext = "." + req.FileType
	}
	if ext == "" {
		ext = ".pdf"
	}
	fileName := strings.TrimSuffix(req.FileName, ext) + ext
	if fileName == ext {
		fileName = "document" + ext
	}

	batchID, uploadURL, err := c.applyUploadURLs(ctx, fileName, ext)
	if err != nil {
		return nil, fmt.Errorf("MinerU Cloud apply upload URLs: %w", err)
	}

	if err := c.uploadFile(ctx, uploadURL, content); err != nil {
		return nil, fmt.Errorf("MinerU Cloud file upload: %w", err)
	}

	mdContent, imageRefs, err := c.pollBatchResult(ctx, batchID)
	if err != nil {
		return nil, fmt.Errorf("MinerU Cloud poll: %w", err)
	}

	mdContent, imageRefs = ensureOriginalImageRef(req, mdContent, imageRefs)

	return &types.ReadResult{
		MarkdownContent: mdContent,
		ImageRefs:       imageRefs,
	}, nil
}

// --- batch upload API ---

type batchApplyResponse struct {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the wrapped cause for HTTP status; a 403 on a presigned URL usually means expired signature or header mismatch — retry the whole Read (fresh URLs are issued per call).
  2. Verify the file size is within the MinerU/storage upload limit; compress or split large documents.
  3. Ensure stable network connectivity to the storage host; retry after transient failures.
  4. Do not modify the request headers/body relative to what the signature expects.

Example fix

// before: reusing an old presigned URL after a long delay
uploadURL := cachedUploadURLFromYesterday
client.uploadFile(ctx, uploadURL, content) // 403 expired
// after: always fetch fresh URLs immediately before upload
batchID, uploadURL, err := client.applyUploadURLs(ctx, fileName, ext)
if err != nil { return nil, err }
if err := client.uploadFile(ctx, uploadURL, content); err != nil { return nil, err }
Defensive patterns

Strategy: retry

Validate before calling

const maxUploadBytes = 200 << 20 // confirm against MinerU/storage limits
if int64(len(content)) > maxUploadBytes {
    return fmt.Errorf("document too large to upload: %d bytes", len(content))
}

Try / catch

res, err := converter.Read(ctx, req)
if err != nil {
    if strings.Contains(err.Error(), "file upload") {
        log.Warnf("upload to presigned URL failed: %v — retrying Read (fresh presigned URLs)", err)
        return retryWithBackoff(ctx, 3, func() error { return readAgain(ctx, req) })
    }
    return err
}

Prevention

When it happens

Trigger: Read -> uploadFile returned an error when PUT-ing the document bytes to the presigned uploadURL: network failure, non-2xx storage response, timeout, or body mismatch with the signed request.

Common situations: Uploading files larger than the storage limit; presigned URL expired between applyUploadURLs and upload (slow local processing); wrong Content-Type/header not matching signature; TLS-intercepting proxy breaking the upload; network interruption mid-upload.

Related errors


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