micro/go-micro · error

API request failed: %w

Error message

API request failed: %w

What it means

Returned by Provider.callAPI when the HTTP transport fails executing the POST to /v1/messages — the request did not complete. The wrapped error is a *url.Error containing the underlying cause (DNS, TLS, timeout, connection refused, or context cancellation).

Source

Thrown at ai/anthropic/anthropic.go:374

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

	// Build HTTP request
	apiURL := strings.TrimRight(p.opts.BaseURL, "/") + "/v1/messages"
	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))
	if err != nil {
		return nil, nil, fmt.Errorf("failed to create request: %w", err)
	}

	// Set headers
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("x-api-key", p.opts.APIKey)
	httpReq.Header.Set("anthropic-version", "2023-06-01")

	// Make request
	httpResp, err := http.DefaultClient.Do(httpReq)
	if err != nil {
		return nil, nil, fmt.Errorf("API request failed: %w", err)
	}
	defer httpResp.Body.Close()

	// Read response
	respBody, err := io.ReadAll(httpResp.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read response: %w", err)
	}
	if httpResp.StatusCode != http.StatusOK {
		return nil, nil, ai.NewHTTPError(httpResp, respBody)
	}

	// Parse response
	var anthropicResp struct {
		Content []struct {
			Type  string          `json:"type"`
			Text  string          `json:"text"`
			ID    string          `json:"id"`

View on GitHub (pinned to 24529f1404)

Solutions

  1. Test connectivity to the endpoint directly: curl -v $BASE_URL/v1/messages.
  2. Check errors.Is(err, context.DeadlineExceeded) to distinguish timeout from other transport failures and raise the deadline if needed.
  3. Verify proxy settings (HTTPS_PROXY/HTTP_PROXY) or configure a custom http.Client with the right transport.
  4. If pointing at a local gateway, confirm the port and that the service is actually listening (connection refused).

Example fix

// before
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
resp, err := provider.Generate(ctx, prompt)
// after
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
resp, err := provider.Generate(ctx, prompt)
if err != nil && errors.Is(err, context.DeadlineExceeded) { /* retry with longer budget */ }
Defensive patterns

Strategy: retry

Validate before calling

func endpointReachable(base string) error {
	u, _ := url.Parse(strings.TrimSpace(base))
	c, err := net.DialTimeout("tcp", net.JoinHostPort(u.Hostname(), portOr(u, "443")), 5*time.Second)
	if err != nil { return err }
	c.Close(); return nil
}

Try / catch

resp, err := provider.Generate(ctx, prompt)
if err != nil {
	switch {
	case errors.Is(err, context.DeadlineExceeded):
		// increase timeout, retry
	case errors.Is(err, context.Canceled):
		// caller cancelled: don't retry
	default:
		// transport error: retry once, then surface with cause
	}
}

Prevention

When it happens

Trigger: http.DefaultClient.Do returns an error: no network/DNS failure, TLS handshake failure, connection refused (wrong port on a self-hosted proxy), client timeout, or the caller's ctx was cancelled or exceeded its deadline.

Common situations: Offline environments or missing HTTPS_PROXY in corporate networks, local Anthropic-compatible proxies (LiteLLM, Ollama gateways) on the wrong host/port, short context deadlines exceeded by long generations.

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 micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/b2e429a9e942426e. Report an issue: GitHub.