micro/go-micro · error
stream API request failed: %w
Error message
stream API request failed: %w
What it means
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.
Source
Thrown at ai/gemini/gemini.go:196
reqBody, err := json.Marshal(apiReq)
if err != nil {
return nil, fmt.Errorf("failed to marshal stream request: %w", err)
}
apiURL := strings.TrimRight(p.opts.BaseURL, "/") +
"/v1beta/models/" + p.opts.Model + ":streamGenerateContent?alt=sse"
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))
if err != nil {
return nil, fmt.Errorf("failed to create stream request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "text/event-stream")
httpReq.Header.Set("x-goog-api-key", p.opts.APIKey)
httpResp, err := http.DefaultClient.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("stream API request failed: %w", err)
}
if httpResp.StatusCode != http.StatusOK {
defer httpResp.Body.Close()
respBody, _ := io.ReadAll(httpResp.Body)
return nil, ai.NewHTTPError(httpResp, respBody)
}
return &streamReader{body: httpResp.Body, scanner: bufio.NewScanner(httpResp.Body)}, nil
}
type streamReader struct {
body io.ReadCloser
scanner *bufio.Scanner
closed bool
}
func (s *streamReader) Recv() (*ai.Response, error) {
for s.scanner.Scan() {
line := strings.TrimSpace(s.scanner.Text())View on GitHub (pinned to 24529f1404)
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.
Example fix
// before
stream, err := provider.Stream(ctx, req)
// after
var netErr net.Error
stream, err := provider.Stream(ctx, req)
if errors.As(err, &netErr) && netErr.Timeout() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
stream, err = provider.Stream(ctx, req)
} Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", host+":443", 3*time.Second)
if err != nil {
return fmt.Errorf("gemini endpoint unreachable: %w", err)
}
conn.Close() Type guard
func isTransientNetworkErr(err error) bool {
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() { return true }
var de *net.DNSError
return errors.As(err, &de) ||
strings.Contains(err.Error(), "connection refused") ||
errors.Is(err, context.Canceled) == false && strings.Contains(err.Error(), "EOF")
} Try / catch
var stream *ai.Stream
err := retry.Do(3, 2*time.Second, func() error {
var e error
stream, e = provider.Stream(ctx, req)
if e != nil && strings.Contains(e.Error(), "stream API request failed") {
return e // retryable transport failure
}
return retry.Stop(e)
}) Prevention
- 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
When it happens
Trigger: http.DefaultClient.Do returned err while posting to :streamGenerateContent — unreachable host, proxy issues, TLS interception, canceled context mid-flight, or network outage.
Common situations: See trigger scenarios.
Related errors
- API request failed: %w
- stream API request failed: %w
- stream API request failed: %w
- deadline exceeded
- API request failed: %w
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/181e7ab35860b316.
Report an issue: GitHub.