gastownhall/beads · error
request failed: %w
Error message
request failed: %w
What it means
The HTTP transport itself failed: httpClient.Do returned an error before any HTTP response was received (DNS failure, connection refused/reset, TLS handshake error, timeout, or request cancellation via ctx). The error is wrapped as 'request failed: %w' with the underlying net/http error in the chain.
Source
Thrown at internal/notion/client.go:282
requestURL := path
if !strings.HasPrefix(requestURL, "http://") && !strings.HasPrefix(requestURL, "https://") {
requestURL = strings.TrimSuffix(c.BaseURL, "/") + path
}
req, err := http.NewRequestWithContext(ctx, method, requestURL, bodyReader)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.Token)
req.Header.Set("Notion-Version", c.NotionVersion)
req.Header.Set("Accept", "application/json")
if requestBody != nil {
req.Header.Set("Content-Type", "application/json")
}
resp, err := httpClient.Do(req) //nolint:gosec // G704: URL is constructed from configured Notion API base, not user input
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer func() { _ = resp.Body.Close() }()
body, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseBytes))
if err != nil {
return nil, fmt.Errorf("read response: %w", err)
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
return body, nil
}
var apiErr struct {
Code string `json:"code"`
Message string `json:"message"`
}
if err := json.Unmarshal(body, &apiErr); err == nil && apiErr.Message != "" {
return nil, fmt.Errorf("Notion API error %s (%d): %s", apiErr.Code, resp.StatusCode, apiErr.Message)
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped error to identify the class (dial tcp / tls / context deadline) and fix accordingly.
- Verify outbound connectivity: curl -v https://api.notion.com/v1/users/me from the same host.
- Configure proxy env vars (HTTPS_PROXY) if behind a corporate proxy, or trust the corporate CA.
- Increase or reset the http.Client timeout used for the Notion client; retry with backoff for transient failures.
Example fix
// before
client := ¬ion.Client{Token: tok, HTTPClient: &http.Client{Timeout: 50 * time.Millisecond}}
// after
client := ¬ion.Client{Token: tok, HTTPClient: &http.Client{Timeout: 30 * time.Second}} Defensive patterns
Strategy: retry
Validate before calling
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.notion.com/v1/users/me", nil)
if err == nil {
if _, err := http.DefaultClient.Do(req); err != nil {
return fmt.Errorf("notion API unreachable: %w", err)
}
} Try / catch
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// backoff and retry
} Prevention
- Set a sane http.Client timeout (e.g. 30s) instead of very short or zero.
- Verify egress/proxy/firewall access to api.notion.com in each environment (CI, prod).
- Use context timeouts so cancellations are intentional and observable.
- Implement exponential backoff for transient transport errors.
When it happens
Trigger: Network unreachable or DNS cannot resolve api.notion.com; corporate proxy/firewall blocking outbound 443; TLS interception with untrusted certs; custom c.HTTPClient with a too-short timeout; context cancelled mid-request.
Common situations: Running in an air-gapped/locked-down CI environment without egress; VPN down; invalid corporate proxy not configured via HTTPS_PROXY; machine clock skew breaking TLS; custom http.Client{Timeout: 100 * time.Millisecond} in tests.
Related errors
- request failed: %w
- oauth: token request failed: %w
- failed to list projects: %w
- failed to remove backup: %w
- clone from remote: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/741013bfd20d6fb2.
Report an issue: GitHub.