gastownhall/beads · error

request failed: %w

Error message

request failed: %w

What it means

This error wraps a failure of c.HTTPClient.Do(httpReq) — the HTTP request to Linear's API never completed with a response. Typical causes are DNS failures, connection refused/timeouts, TLS problems, or the context being canceled mid-flight. It is a transport-level failure, distinct from API errors returned with an HTTP status.

Source

Thrown at internal/linear/client.go:895

	if err != nil {
		return nil, fmt.Errorf("failed to marshal request: %w", err)
	}

	httpReq, err := http.NewRequestWithContext(ctx, "POST", c.Endpoint, bytes.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	httpReq.Header.Set("Content-Type", "application/json")
	authValue, err := c.authHeader()
	if err != nil {
		return nil, err
	}
	httpReq.Header.Set("Authorization", authValue)

	resp, err := c.HTTPClient.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}

	respBody, err := io.ReadAll(io.LimitReader(resp.Body, MaxResponseSize))
	_ = resp.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("API error: %s (status %d)", string(respBody), resp.StatusCode)
	}

	var gqlResp struct {
		Data   json.RawMessage `json:"data"`
		Errors []GraphQLError  `json:"errors,omitempty"`
	}
	if err := json.Unmarshal(respBody, &gqlResp); err != nil {
		return nil, fmt.Errorf("failed to parse response: %w (body: %s)", err, string(respBody))

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check network reachability: curl https://api.linear.app/graphql from the same host
  2. Inspect the wrapped cause (net.Error, context.DeadlineExceeded, x509 errors) via errors.As and handle each class
  3. Increase the HTTP client timeout or retry on transient network errors with backoff
  4. Verify proxy environment variables (HTTP_PROXY/HTTPS_PROXY) and TLS trust store are correct

Example fix

// before
client := &http.Client{} // no timeout; hangs then fails on dead network
// after
client := &http.Client{Timeout: 30 * time.Second}
if err != nil {
    var ne net.Error
    if errors.As(err, &ne) && ne.Timeout() {
        // retry with backoff
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight connectivity check
resp, err := http.Head("https://api.linear.app")
if err != nil {
    return fmt.Errorf("linear unreachable: %w", err)
}
resp.Body.Close()

Try / catch

var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
    // retry with backoff
}
if errors.Is(err, context.Canceled) {
    // caller canceled; do not retry
}

Prevention

When it happens

Trigger: Network outage or DNS failure resolving api.linear.app; connection timeout because HTTPClient has no/short Timeout and Linear is slow or unreachable; ctx canceled while the request is in flight; TLS certificate errors (corporate proxy, wrong system clock); invalid proxy settings in the environment.

Common situations: CI runners without network egress; corporate proxy/VPN blocking api.linear.app; HTTP_CLIENT_TIMEOUT configured too aggressively; container DNS misconfiguration; server shutting down and canceling the context.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/59cf98d61cc18573. Report an issue: GitHub.