Tencent/WeKnora · error
download zip status %d
Error message
download zip status %d
What it means
The ZIP download request returned an HTTP status other than 200, and downloadAndExtractZip rejects it with 'download zip status %d' (mineru_cloud_converter.go:366). Typical statuses: 403/404 for expired or revoked result URLs, 401 for auth problems, 5xx for storage-side errors. The body is not attempted because it won't contain a valid ZIP.
Source
Thrown at internal/infrastructure/docparser/mineru_cloud_converter.go:366
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
entries := make(map[string]*zip.File)
for _, f := range zr.File {
entries[f.Name] = f
if strings.HasSuffix(f.Name, ".md") {View on GitHub (pinned to 988cbb0330)
Solutions
- Check the status code in the message: 403/404 means the link expired or results were purged — re-run the batch conversion for a fresh full_zip_url.
- For 429, back off and retry with jitter; respect the storage service rate limits.
- For 5xx, retry after a delay; if persistent, check MinerU Cloud service health.
- Download results promptly after the task reaches done state to avoid link expiry.
Example fix
// before
if resp.StatusCode != http.StatusOK {
return "", nil, fmt.Errorf("download zip status %d", resp.StatusCode)
}
// after — include body hint for diagnosis
if resp.StatusCode != http.StatusOK {
b, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
return "", nil, fmt.Errorf("download zip status %d: %s", resp.StatusCode, string(b))
} Defensive patterns
Strategy: try-catch
Validate before calling
if item.FullZipURL == "" {
return errors.New("no full_zip_url to download")
} Try / catch
md, images, err := pollBatchResult(ctx, batchID)
if err != nil {
var statusErr *ZipDownloadStatusError
if errors.As(err, &statusErr) && (statusErr.Code == 403 || statusErr.Code == 404) {
// link expired / results purged: re-run the batch conversion
return resubmitBatch(ctx, doc)
}
if statusErr != nil && statusErr.Code == 429 {
time.Sleep(backoff)
return pollBatchResult(ctx, batchID)
}
return err
} Prevention
- Download the ZIP immediately once state=done to beat link expiry.
- Branch on the status code: 403/404 re-submit, 429 back off, 5xx retry.
- Keep batch IDs short-lived in your own storage since MinerU results expire.
When it happens
Trigger: extractDoneResult -> downloadAndExtractZip GETs full_zip_url and receives e.g. 403 (presigned URL expired), 404 (results purged), 429 (rate limited), or 5xx from the storage backend.
Common situations: Polling results long after task completion once MinerU Cloud expires download links; sharing/leaking the URL across environments with different access; storage outage returning 5xx; hammering the endpoint causing 429.
Related errors
- download zip: %w
- create download request: %w
- download failed with status %d
- download file: %w
- fetch failed: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/f3298f9a47b0d678.
Report an issue: GitHub.