Tencent/WeKnora · error

HTTP %d for %s

Error message

HTTP %d for %s

What it means

DownloadBytes requires an HTTP 200 response; any other status (404, 403, 500, redirects not followed to a 200, etc.) produces "HTTP <status> for <url>". The function treats non-OK as failure and returns no body.

Source

Thrown at internal/utils/httputil.go:31

	MaxRedirects: 10,
})

// DownloadBytes fetches the content at the given HTTP(S) URL and returns the
// raw bytes. It reuses a package-level http.Client with a 60-second timeout.
func DownloadBytes(url string) ([]byte, error) {
	if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
		return nil, fmt.Errorf("unsupported URL scheme: %s", url)
	}
	if err := ValidateURLForSSRF(url); err != nil {
		return nil, fmt.Errorf("URL rejected by SSRF policy: %w", err)
	}
	resp, err := defaultHTTPClient.Get(url)
	if err != nil {
		return nil, fmt.Errorf("HTTP GET: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
	}
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read body: %w", err)
	}
	return data, nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Verify the URL is correct and publicly accessible (curl -I it)
  2. Add required auth via a client that supports headers instead of DownloadBytes, or pre-sign the URL
  3. Handle the status code in the error message — retry 429/5xx with backoff, fail fast on 4xx
  4. Check for expired/rotated links (signed URLs past expiry return 403)

Example fix

// before
DownloadBytes("https://example.com/old-file.pdf") // 404
// after
resp, err := http.Head("https://example.com/file.pdf")
if err == nil && resp.StatusCode == http.StatusOK {
    data, err := DownloadBytes("https://example.com/file.pdf")
}
Defensive patterns

Strategy: retry

Validate before calling

resp, err := http.Head(url)
if err != nil || resp.StatusCode != http.StatusOK {
    return fmt.Errorf("URL not downloadable (status %v)", resp)
}

Try / catch

data, err := DownloadBytes(url)
if err != nil {
    if strings.Contains(err.Error(), "HTTP ") {
        var code int
        if _, scanErr := fmt.Sscanf(err.Error(), "HTTP %d", &code); scanErr == nil {
            if code == 429 || code >= 500 { /* retry with backoff */ } else { /* permanent — fix URL/auth */ }
        }
    }
}

Prevention

When it happens

Trigger: Calling DownloadBytes against a URL that returns a non-200 status: missing resource, auth-required endpoint, rate limiting (429), server error, or a redirect chain not ending in 200 (the default client follows redirects, so this means the final response was non-200).

Common situations: Dead or moved download links, private assets requiring credentials, CDN rate limits, URLs behind login walls, or temporary upstream 5xx during deployments.

Related errors


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