{"record":{"id":"b699437591cb5071","repo":"micro/go-micro","slug":"api-request-failed-w-b69943","errorCode":null,"errorMessage":"API request failed: %w","messagePattern":"API request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/atlascloud/atlascloud.go","lineNumber":442,"sourceCode":"\nfunc (p *Provider) callAPI(ctx context.Context, phase string, req map[string]any) (*ai.Response, map[string]any, error) {\n\treqBody, err := json.Marshal(req)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n\n\tapiURL := strings.TrimRight(p.opts.BaseURL, \"/\") + \"/v1/chat/completions\"\n\thttpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Authorization\", \"Bearer \"+p.opts.APIKey)\n\n\thttpResp, err := http.DefaultClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"API request failed: %w\", err)\n\t}\n\tdefer httpResp.Body.Close()\n\n\trespBody, _ := io.ReadAll(httpResp.Body)\n\tif httpResp.StatusCode != http.StatusOK {\n\t\tretryAfter := time.Duration(0)\n\t\tvar retryErr interface{ RetryAfter() time.Duration }\n\t\tif errors.As(ai.NewHTTPError(httpResp, respBody), &retryErr) {\n\t\t\tretryAfter = retryErr.RetryAfter()\n\t\t}\n\t\treturn nil, nil, &atlascloudAPIError{Status: httpResp.Status, Code: httpResp.StatusCode, Retry: retryAfter, Phase: phase, Summary: atlascloudRequestSummary(req), Body: string(respBody)}\n\t}\n\n\tvar chatResp struct {\n\t\tChoices []struct {\n\t\t\tMessage struct {\n\t\t\t\tContent   string          `json:\"content\"`\n\t\t\t\tToolCalls []atlasToolCall `json:\"tool_calls\"`","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/atlascloud/atlascloud.go#L424-L460","documentation":"callAPI in the AtlasCloud provider wraps any error returned by http.DefaultClient.Do when POSTing a chat-completion request. It means the HTTP round trip itself failed — no response was received from the server. This library throws it so the underlying transport error (DNS, TLS, timeout, connection reset) is preserved via %w for errors.Is/As inspection.","triggerScenarios":"Generate -> callAPI issues http.NewRequestWithContext and calls http.DefaultClient.Do(httpReq); any non-nil error from Do (DNS failure, connection refused, TLS handshake failure, context deadline exceeded while awaiting the response, request cancellation) triggers this wrap.","commonSituations":"Wrong or unreachable BaseURL (typo, missing scheme, private endpoint), no network/DNS in the environment, corporate proxy blocking the host, very slow model responses exceeding the client timeout causing context deadline, or the caller's ctx being cancelled mid-request.","solutions":["Verify p.opts.BaseURL is a correct, reachable URL (curl -v $BASEURL/chat/completions) and includes the https:// scheme.","Check basic connectivity/DNS from the host: ping or curl the API host; check proxy env vars (HTTP_PROXY/HTTPS_PROXY).","Inspect the wrapped error with errors.Is(err, context.DeadlineExceeded) / net.Error.Timeout() and increase the http.Client timeout or extend the context deadline for long completions.","Retry with exponential backoff for transient network errors; check ctx cancellation if requests are being aborted."],"exampleFix":"// before\nresp, err := http.DefaultClient.Do(req)\n// after\nclient := &http.Client{Timeout: 120 * time.Second}\nresp, err := client.Do(req)","handlingStrategy":"retry","validationCode":"u, err := url.Parse(baseURL)\nif err != nil || u.Host == \"\" {\n    return fmt.Errorf(\"invalid AtlasCloud BaseURL: %v\", err)\n}\nif _, err := net.LookupHost(u.Hostname()); err != nil {\n    return fmt.Errorf(\"cannot resolve AtlasCloud host: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"resp, err := provider.Generate(ctx, req)\nif err != nil {\n    var nerr net.Error\n    if errors.As(err, &nerr) && nerr.Timeout() {\n        // retry with backoff / larger timeout\n    }\n    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {\n        // respect cancellation; do not blind-retry\n    }\n    return fmt.Errorf(\"atlascloud chat request failed: %w\", err)\n}","preventionTips":["Validate BaseURL at startup with url.Parse and a health-check ping.","Use an http.Client with an explicit Timeout sized for LLM latency, not http.DefaultClient.","Add exponential backoff retry for transient net.Error conditions.","Always propagate a cancellable context and honor cancellation."],"tags":["network","http-client","go","atlascloud"],"backgroundTag":"http-request-transport-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}