henrygd/beszel · error

http get

Error message

http get: %w

What it means

Thrown by downloadFile when the HTTP client's Do call fails — the request never completed. This wraps DNS resolution failures, connection refused/timeouts (client timeout is 60s), TLS errors, or proxy problems. No response body is available at this point.

Solutions

  1. Test connectivity to the URL with curl from the same machine
  2. Check DNS resolution and proxy env vars (HTTP_PROXY/HTTPS_PROXY)
  3. Retry later if the mirror is transiently down; pin to an alternate mirror URL
  4. Inspect the wrapped %w error: dial tcp / no such host / x509 tell you the layer

Example fix

// before
resp, err := client.Do(req)
if err != nil {
	return fmt.Errorf("http get: %w", err)
}
// after
var resp *http.Response
for i := 0; i < 3; i++ {
	resp, err = client.Do(req)
	if err == nil {
		break
	}
	time.Sleep(time.Duration(1<<i) * time.Second) // retry transient network errors
}
if err != nil {
	return fmt.Errorf("http get: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

conn, err := net.DialTimeout("tcp", host+":443", 5*time.Second)
if err != nil {
	return fmt.Errorf("cannot reach %s: %w", host, err)
}
conn.Close()

Try / catch

if err := downloadFile(url, dest, sha); err != nil {
	if strings.HasPrefix(err.Error(), "http get:") {
		time.Sleep(5 * time.Second)
		err = downloadFile(url, dest, sha) // retry transient network failure
	}
	if err != nil {
		return err
	}
}

Prevention

When it happens

Trigger: Running fetchsmartctl behind a firewall/proxy, offline, or against an unreachable/moved download host; TLS handshake failure.

Common situations: CI runners without internet egress; corporate proxy requiring auth; smartmontools download mirror temporarily down or DNS records changed; IPv6-only egress failures.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/339a7ba8c924913e. Report an issue: GitHub.

Appendix: source

Thrown at agent/tools/fetchsmartctl/main.go:60

}

func downloadFile(url, dest, shaHex string) error {
	// Prepare destination
	if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
		return fmt.Errorf("create dir: %w", err)
	}

	// HTTP client
	client := &http.Client{Timeout: 60 * time.Second}
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return fmt.Errorf("new request: %w", err)
	}
	req.Header.Set("User-Agent", "beszel-fetchsmartctl/1.0")

	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("http get: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("unexpected HTTP status: %s", resp.Status)
	}

	tmp := dest + ".tmp"
	f, err := os.OpenFile(tmp, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
	if err != nil {
		return fmt.Errorf("open tmp: %w", err)
	}

	// Determine hash algorithm based on length (SHA1=40, SHA256=64)
	var hasher hash.Hash
	if shaHex := strings.TrimSpace(shaHex); shaHex != "" {
		cleanSha := strings.ToLower(strings.ReplaceAll(shaHex, " ", ""))
		switch len(cleanSha) {

View on GitHub (pinned to b38fb7dafa)