{"record":{"id":"181e7ab35860b316","repo":"micro/go-micro","slug":"stream-api-request-failed-w-181e7a","errorCode":null,"errorMessage":"stream API request failed: %w","messagePattern":"stream API request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/gemini/gemini.go","lineNumber":196,"sourceCode":"\n\treqBody, err := json.Marshal(apiReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal stream request: %w\", err)\n\t}\n\n\tapiURL := strings.TrimRight(p.opts.BaseURL, \"/\") +\n\t\t\"/v1beta/models/\" + p.opts.Model + \":streamGenerateContent?alt=sse\"\n\thttpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create stream request: %w\", err)\n\t}\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"Accept\", \"text/event-stream\")\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, fmt.Errorf(\"stream API request failed: %w\", err)\n\t}\n\tif httpResp.StatusCode != http.StatusOK {\n\t\tdefer httpResp.Body.Close()\n\t\trespBody, _ := io.ReadAll(httpResp.Body)\n\t\treturn nil, ai.NewHTTPError(httpResp, respBody)\n\t}\n\treturn &streamReader{body: httpResp.Body, scanner: bufio.NewScanner(httpResp.Body)}, nil\n}\n\ntype streamReader struct {\n\tbody    io.ReadCloser\n\tscanner *bufio.Scanner\n\tclosed  bool\n}\n\nfunc (s *streamReader) Recv() (*ai.Response, error) {\n\tfor s.scanner.Scan() {\n\t\tline := strings.TrimSpace(s.scanner.Text())","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/gemini/gemini.go#L178-L214","documentation":"Stream's HTTP POST to the Gemini streaming endpoint failed at the transport layer: DNS failure, connection refused, TLS error, timeout, or context cancellation. No HTTP response was received, so this is a network-level problem, not an API error status. The wrapped %w error carries the net/http detail.","triggerScenarios":"http.DefaultClient.Do returned err while posting to :streamGenerateContent — unreachable host, proxy issues, TLS interception, canceled context mid-flight, or network outage.","commonSituations":"See trigger scenarios.","solutions":["Read the wrapped error: 'connection refused'/'no such host' means reachability — check network, proxy, and BaseURL.","If it says 'context deadline exceeded', increase the request timeout or check upstream cancellation.","Verify outbound HTTPS access to the Gemini endpoint (curl the BaseURL).","Configure HTTP_PROXY/HTTPS_PROXY correctly or bypass the proxy for this host.","Wrap the call in bounded retry with backoff for transient network failures."],"exampleFix":"// before\nstream, err := provider.Stream(ctx, req)\n// after\nvar netErr net.Error\nstream, err := provider.Stream(ctx, req)\nif errors.As(err, &netErr) && netErr.Timeout() {\n    ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)\n    defer cancel()\n    stream, err = provider.Stream(ctx, req)\n}","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", host+\":443\", 3*time.Second)\nif err != nil {\n    return fmt.Errorf(\"gemini endpoint unreachable: %w\", err)\n}\nconn.Close()","typeGuard":"func isTransientNetworkErr(err error) bool {\n    var ne net.Error\n    if errors.As(err, &ne) && ne.Timeout() { return true }\n    var de *net.DNSError\n    return errors.As(err, &de) ||\n        strings.Contains(err.Error(), \"connection refused\") ||\n        errors.Is(err, context.Canceled) == false && strings.Contains(err.Error(), \"EOF\")\n}","tryCatchPattern":"var stream *ai.Stream\nerr := retry.Do(3, 2*time.Second, func() error {\n    var e error\n    stream, e = provider.Stream(ctx, req)\n    if e != nil && strings.Contains(e.Error(), \"stream API request failed\") {\n        return e // retryable transport failure\n    }\n    return retry.Stop(e)\n})","preventionTips":["Use bounded retries with exponential backoff for streaming requests","Set explicit generous timeouts on the context (SSE streams are long-lived)","Verify proxy env vars (HTTP(S)_PROXY, NO_PROXY) allow the Gemini host","Health-check connectivity before long-running stream sessions"],"tags":["network","http-client","gemini","streaming","timeout"],"backgroundTag":"network-request-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}