micro/go-micro · error
failed to create stream request: %w
Error message
failed to create stream request: %w
What it means
Stream failed at http.NewRequestWithContext while building the streaming POST to /v1beta/models/<model>:streamGenerateContent?alt=sse. This almost always means the constructed URL was invalid (bad model name characters, malformed BaseURL) or the context was already canceled. The wrapped error states which.
Source
Thrown at ai/gemini/gemini.go:188
if req.SystemPrompt != "" {
apiReq["system_instruction"] = map[string]any{
"parts": []map[string]any{{"text": req.SystemPrompt}},
}
}
if p.opts.MaxTokens > 0 {
apiReq["generationConfig"] = map[string]any{"maxOutputTokens": p.opts.MaxTokens}
}
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 {View on GitHub (pinned to 24529f1404)
Solutions
- Trim and validate opts.Model and opts.BaseURL (no spaces, valid URL) before calling Stream.
- Check the wrapped %w error: if it mentions 'context canceled', fix the upstream context lifecycle.
- Print the composed URL and validate it parses with net/url.Parse.
- Verify BaseURL lacks a trailing path typo or scheme issue (must include http:// or https://).
Example fix
// before
p.opts.Model = os.Getenv("GEMINI_MODEL")
// after
model := strings.TrimSpace(os.Getenv("GEMINI_MODEL"))
if model == "" || strings.ContainsAny(model, " /?") {
return nil, fmt.Errorf("invalid model name: %q", model)
}
p.opts.Model = model Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(baseURL))
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid BaseURL: %q", baseURL)
}
model := strings.TrimSpace(modelName)
if model == "" || strings.ContainsAny(model, " ?#/") {
return fmt.Errorf("invalid model name: %q", model)
} Type guard
func validGeminiOpts(baseURL, model string) bool {
u, err := url.Parse(baseURL)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != "" &&
strings.TrimSpace(model) == model && model != ""
} Try / catch
stream, err := provider.Stream(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "failed to create stream request") && ctx.Err() != nil {
return fmt.Errorf("context canceled before streaming: %w", ctx.Err())
}
return err
} Prevention
- Trim env-derived model names and BaseURLs at config load time
- Validate provider configuration once at startup, not per request
- Avoid reusing contexts that may already be canceled
When it happens
Trigger: Calling Stream with an opts.Model containing characters invalid in a URL path, a malformed opts.BaseURL (e.g. with spaces or control chars), or a ctx that was canceled before the call.
Common situations: Model name pasted with whitespace/newline; BaseURL set to a proxy URL with stray characters; passing an already-expired/canceled context from an upstream timeout.
Related errors
- failed to create request: %w
- failed to create stream request: %w
- failed to create stream request: %w
- stream API request failed: %w
- stream API error (%s): %s
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/90aa47a7fbb0ac9d.
Report an issue: GitHub.