micro/go-micro · error
failed to create request: %w
Error message
failed to create request: %w
What it means
callAPI failed constructing the http.Request for POST /v1beta/models/<model>:generateContent, typically because the composed URL was invalid or the context was already canceled. The wrapped %w error distinguishes url construction issues from context cancellation.
Source
Thrown at ai/gemini/gemini.go:295
if s.closed {
return nil
}
s.closed = true
return s.body.Close()
}
func (p *Provider) callAPI(ctx context.Context, req map[string]any) (*ai.Response, []map[string]any, error) {
reqBody, err := json.Marshal(req)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal request: %w", err)
}
apiURL := strings.TrimRight(p.opts.BaseURL, "/") +
"/v1beta/models/" + p.opts.Model + ":generateContent"
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))
if err != nil {
return nil, nil, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("x-goog-api-key", p.opts.APIKey)
httpResp, err := http.DefaultClient.Do(httpReq)
if err != nil {
return nil, nil, fmt.Errorf("API request failed: %w", err)
}
defer httpResp.Body.Close()
respBody, _ := io.ReadAll(httpResp.Body)
if httpResp.StatusCode != http.StatusOK {
return nil, nil, ai.NewHTTPError(httpResp, respBody)
}
var geminiResp struct {
Candidates []struct {View on GitHub (pinned to 24529f1404)
Solutions
- Sanitize opts.Model and opts.BaseURL: trim whitespace and confirm BaseURL parses via net/url.Parse with a valid scheme.
- If the wrapped error is 'context canceled', audit the caller's context lifecycle and deadlines.
- Log the composed URL to spot path-unsafe characters from the model name.
- Validate configuration at startup rather than at request time.
Example fix
// before
provider, _ := gemini.NewProvider(gemini.WithBaseURL(cfg.Endpoint))
// after
u, err := url.Parse(cfg.Endpoint)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("invalid gemini BaseURL: %q", cfg.Endpoint)
}
provider, _ := gemini.NewProvider(gemini.WithBaseURL(strings.TrimRight(cfg.Endpoint, " "))) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(baseURL))
if err != nil || u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("invalid gemini BaseURL: %q", baseURL)
}
if strings.TrimSpace(model) != model || model == "" {
return fmt.Errorf("invalid gemini model: %q", model)
} Type guard
func validCallAPIConfig(baseURL, model string) bool {
u, err := url.Parse(baseURL)
return err == nil && u.Host != "" && (u.Scheme == "http" || u.Scheme == "https") &&
model != "" && strings.TrimSpace(model) == model
} Try / catch
resp, err := provider.Generate(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "failed to create request") {
if ctx.Err() != nil { return fmt.Errorf("canceled: %w", ctx.Err()) }
return fmt.Errorf("bad provider config (check BaseURL/model): %w", err)
}
return err
} Prevention
- Sanitize and validate BaseURL/model at provider construction time
- Strip whitespace from all env-derived configuration
- Ensure parent contexts are alive when issuing calls
When it happens
Trigger: Calling a non-streaming Gemini method with an opts.Model or opts.BaseURL that yields an unparsable URL (spaces, control characters, missing scheme), or with an already-canceled ctx.
Common situations: Model name from env containing a newline/trailing space; BaseURL misconfigured for a self-hosted gateway without scheme; parent context canceled before the call executes.
Related errors
- failed to create stream request: %w
- failed to create stream request: %w
- failed to create request: %w
- failed to create stream request: %w
- failed to create request: %w
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/c495eb0535937f15.
Report an issue: GitHub.