{"record":{"id":"90aa47a7fbb0ac9d","repo":"micro/go-micro","slug":"failed-to-create-stream-request-w-90aa47","errorCode":null,"errorMessage":"failed to create stream request: %w","messagePattern":"failed to create stream request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/gemini/gemini.go","lineNumber":188,"sourceCode":"\tif req.SystemPrompt != \"\" {\n\t\tapiReq[\"system_instruction\"] = map[string]any{\n\t\t\t\"parts\": []map[string]any{{\"text\": req.SystemPrompt}},\n\t\t}\n\t}\n\tif p.opts.MaxTokens > 0 {\n\t\tapiReq[\"generationConfig\"] = map[string]any{\"maxOutputTokens\": p.opts.MaxTokens}\n\t}\n\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 {","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/gemini/gemini.go#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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://)."],"exampleFix":"// before\np.opts.Model = os.Getenv(\"GEMINI_MODEL\")\n// after\nmodel := strings.TrimSpace(os.Getenv(\"GEMINI_MODEL\"))\nif model == \"\" || strings.ContainsAny(model, \" /?\") {\n    return nil, fmt.Errorf(\"invalid model name: %q\", model)\n}\np.opts.Model = model","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(baseURL))\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid BaseURL: %q\", baseURL)\n}\nmodel := strings.TrimSpace(modelName)\nif model == \"\" || strings.ContainsAny(model, \" ?#/\") {\n    return fmt.Errorf(\"invalid model name: %q\", model)\n}","typeGuard":"func validGeminiOpts(baseURL, model string) bool {\n    u, err := url.Parse(baseURL)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\" &&\n        strings.TrimSpace(model) == model && model != \"\"\n}","tryCatchPattern":"stream, err := provider.Stream(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to create stream request\") && ctx.Err() != nil {\n        return fmt.Errorf(\"context canceled before streaming: %w\", ctx.Err())\n    }\n    return err\n}","preventionTips":["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"],"tags":["http","url","gemini","streaming","request-construction"],"backgroundTag":"invalid-request-url","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}