affaan-m/ECC · error
fetch %s: %w
Error message
fetch %s: %w
What it means
Wrapped error from FetchWithTimeout in golang-patterns, raised on the network round-trip. After the request is built, http.DefaultClient.Do(req) is called; any failure is wrapped as fmt.Errorf("fetch %s: %w", url, err). This message means the HTTP client could not successfully complete the exchange with the server - DNS, connection, TLS, or the context deadline fired.
Source
Thrown at skills/golang-patterns/SKILL.md:212
close(results)
}
```
### Context for Cancellation and Timeouts
```go
func FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("fetch %s: %w", url, err)
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
```
### Graceful Shutdown
```go
func GracefulShutdown(server *http.Server) {
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)View on GitHub (pinned to 01e15490f0)
Solutions
- Classify with errors.Is against url.Error and net.Error; retry only on Timeout() || Temporary().
- Increase the context timeout (or make it configurable) for endpoints known to be slow.
- Verify reachability with curl/wget and inspect DNS + TLS from the same environment.
- Check HTTP_PROXY/HTTPS_PROXY/NO_PROXY if a proxy is in play.
- Use a tuned *http.Client (custom Transport, DialContext, IdleConnTimeout) instead of DefaultClient for production callers.
Example fix
// before
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("fetch %s: %w", url, err)
}
// after - separate retriable network errors from final failures
resp, err := http.DefaultClient.Do(req)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && (netErr.Timeout() || netErr.Temporary()) {
return nil, retryable(fmt.Errorf("fetch %s: %w", url, err))
}
return nil, fmt.Errorf("fetch %s: %w", url, err)
} Defensive patterns
Strategy: retry
Validate before calling
func reachable(ctx context.Context, urlStr string) error {
u, err := url.Parse(urlStr)
if err != nil || u.Host == "" {
return fmt.Errorf("no host to dial")
}
// best-effort DNS preflight
_, err = net.DefaultResolver.LookupHost(ctx, u.Hostname())
return err
} Type guard
func isRetriableHTTPError(err error) bool {
var netErr net.Error
if errors.As(err, &netErr) && (netErr.Timeout() || netErr.Temporary()) {
return true
}
var ue *url.Error
return errors.As(err, &ue) // url.Error wraps transient op errors
} Try / catch
var body []byte
err := retryWithBackoff(func() error {
resp, err := client.Do(req)
if err != nil {
if isRetriableHTTPError(err) {
return err // retriable
}
return errwrap.Stop(err) // final
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return fmt.Errorf("status %d", resp.StatusCode)
}
body, err = io.ReadAll(resp.Body)
return err
}) Prevention
- Use a configured *http.Client with sensible Transport timeouts, not DefaultClient.
- Set a context deadline appropriate to the endpoint's latency.
- Retry only on Timeout()/Temporary() with bounded backoff.
- Check proxy env (HTTP_PROXY/HTTPS_PROXY) when debugging.
When it happens
Trigger: Calling FetchWithTimeout(ctx, url) where http.DefaultClient.Do(req) returns a non-nil error. Concrete triggers: DNS resolution failure, TCP connection refused or timed out, TLS handshake error, the 5-second context deadline exceeded, a proxy error, or a mid-stream reset.
Common situations: Target host is wrong or unreachable from the runtime (network policy, firewall); the 5*time.Second timeout is too short for slow endpoints; TLS certificate is expired or untrusted; HTTP_PROXY/HTTPS_PROXY env vars point at an unreachable proxy; IPv6-only host reached from an IPv4-only network.
Related errors
- create request: %w
- HTTP ${res.status}
- open failed (HTTP ${res.statusCode})
- Codex review timed out
- get user %s: %w
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/f2cba512f5266fae.
Report an issue: GitHub.