{"record":{"id":"422d227d0fdd9b89","repo":"micro/go-micro","slug":"api-request-failed-w-422d22","errorCode":null,"errorMessage":"API request failed: %w","messagePattern":"API request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/gemini/gemini.go","lineNumber":303,"sourceCode":"\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, \"/\") +\n\t\t\"/v1beta/models/\" + p.opts.Model + \":generateContent\"\n\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(\"x-goog-api-key\", 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\treturn nil, nil, ai.NewHTTPError(httpResp, respBody)\n\t}\n\n\tvar geminiResp struct {\n\t\tCandidates []struct {\n\t\t\tContent struct {\n\t\t\t\tParts []struct {\n\t\t\t\t\tText         string          `json:\"text\"`\n\t\t\t\t\tFunctionCall *functionCallPB `json:\"functionCall\"`\n\t\t\t\t} `json:\"parts\"`\n\t\t\t} `json:\"content\"`\n\t\t} `json:\"candidates\"`\n\t}","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/gemini/gemini.go#L285-L321","documentation":"callAPI's HTTP POST to the Gemini generateContent endpoint failed at the transport layer before any response arrived — DNS, connection, TLS, or timeout/context cancellation. This is a network-level failure, distinct from HTTP error statuses, which the library reports via ai.NewHTTPError instead.","triggerScenarios":"http.DefaultClient.Do returned a non-nil error while calling :generateContent — unreachable host, refused connection, TLS failure, proxy error, or canceled/deadline-exceeded context.","commonSituations":"No internet or DNS outage; firewall/proxy blocking generativelanguage.googleapis.com; wrong BaseURL host; overly tight context deadline on large prompts.","solutions":["Check the wrapped error type: 'no such host'/'connection refused' → fix network, proxy, or BaseURL.","On 'context deadline exceeded', increase the timeout budget for the request.","Verify connectivity with curl to the configured BaseURL.","Add retry-with-backoff around the call for transient network faults."],"exampleFix":"// before\nresp, err := provider.Generate(ctx, req)\nif err != nil { return err }\n// after\nresp, err := provider.Generate(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"context deadline exceeded\") {\n        ctx2, cancel := context.WithTimeout(context.Background(), 120*time.Second)\n        defer cancel()\n        resp, err = provider.Generate(ctx2, req)\n    }\n    if err != nil { return err }\n}","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", host+\":443\", 3*time.Second)\nif err != nil {\n    return fmt.Errorf(\"cannot reach gemini endpoint %s: %w\", host, err)\n}\nconn.Close()","typeGuard":"func isTransportFailure(err error) bool {\n    if err == nil { return false }\n    var ne net.Error\n    if errors.As(err, &ne) { return true }\n    var de *net.DNSError\n    return errors.As(err, &de) || strings.Contains(err.Error(), \"API request failed\")\n}","tryCatchPattern":"resp, err := provider.Generate(ctx, req)\nif err != nil && isTransportFailure(err) {\n    for attempt := 0; attempt < 3; attempt++ {\n        time.Sleep(time.Duration(1<<attempt) * time.Second)\n        resp, err = provider.Generate(ctx, req)\n        if err == nil || !isTransportFailure(err) { break }\n    }\n}","preventionTips":["Wrap non-streaming calls in retry with exponential backoff","Give large prompts generous context deadlines","Check proxy/firewall rules for the Gemini API host","Distinguish transport failures from ai.NewHTTPError before retrying"],"tags":["network","http-client","gemini","timeout","connectivity"],"backgroundTag":"network-request-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}