Tencent/WeKnora · error

download zip: %w

Error message

download zip: %w

What it means

The HTTP GET on the MinerU Cloud result ZIP URL failed at the transport level, wrapped as 'download zip: %w' by downloadAndExtractZip (mineru_cloud_converter.go:362). This is a client.Get error: DNS failure, TLS error, connection refused/reset, redirect limit exceeded, or the SSRF-safe client's 120s timeout. The request never got a usable HTTP response.

Source

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

		return "", nil, fmt.Errorf("extract zip: %w", err)
	}

	logger.Infof(context.Background(), "[MinerUCloud] parsed (zip), markdown=%d chars, images=%d", len(md), len(imageRefs))
	return md, imageRefs, nil
}

// --- ZIP handling ---

var imgRefPattern = regexp.MustCompile(`!\[[^\]]*\]\(([^)]+)\)`)

func downloadAndExtractZip(zipURL string) (string, []types.ImageRef, error) {
	if err := utils.ValidateURLForSSRF(zipURL); err != nil {
		return "", nil, fmt.Errorf("zip URL blocked by SSRF check: %v", err)
	}
	client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 120 * time.Second, MaxRedirects: 5})
	resp, err := client.Get(zipURL)
	if err != nil {
		return "", nil, fmt.Errorf("download zip: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", nil, fmt.Errorf("download zip status %d", resp.StatusCode)
	}

	zipData, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", nil, fmt.Errorf("read zip body: %w", err)
	}

	zr, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData)))
	if err != nil {
		return "", nil, fmt.Errorf("open zip: %w", err)
	}

	// Find .md files
	var mdFiles []string

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Read the wrapped cause: timeout vs DNS vs TLS vs redirect-limit tells you which knob to adjust.
  2. For large files on slow links, raise the client timeout (currently 120s) in the SSRFSafeHTTPClientConfig.
  3. Verify egress network access to the storage host from the machine running the converter.
  4. If the URL expired, re-run the batch conversion to obtain a fresh full_zip_url.

Example fix

// before
client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 120 * time.Second, MaxRedirects: 5})
// after — longer timeout for large archives
client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 300 * time.Second, MaxRedirects: 5})
Defensive patterns

Strategy: retry

Validate before calling

u, err := url.Parse(zipURL)
if err != nil {
    return err
}
conn, err := net.DialTimeout("tcp", net.JoinHostPort(u.Hostname(), u.Port()), 5*time.Second)
if err != nil {
    return fmt.Errorf("storage host unreachable: %w", err)
}
conn.Close()

Try / catch

var md string
var images []types.ImageRef
var err error
for attempt := 0; attempt < 3; attempt++ {
    md, images, err = pollBatchResult(ctx, batchID)
    if err == nil || !strings.Contains(err.Error(), "download zip:") {
        break
    }
    time.Sleep(time.Duration(attempt+1) * time.Second)
}

Prevention

When it happens

Trigger: extractDoneResult -> downloadAndExtractZip calls the SSRF-safe client's Get on full_zip_url and the round trip fails: unreachable storage host, TLS certificate problems, more than 5 redirects, or download exceeding the 120s timeout.

Common situations: Expired or moved result URLs (404 handled separately — this is pre-response failure); firewall egress rules blocking the storage domain; very large ZIPs on slow links hitting the 120s timeout; redirect chains through a proxy exceeding MaxRedirects: 5.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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