{"record":{"id":"74b433deeef81ef7","repo":"micro/go-micro","slug":"failed-to-marshal-stream-request-w-74b433","errorCode":null,"errorMessage":"failed to marshal stream request: %w","messagePattern":"failed to marshal stream request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/gemini/gemini.go","lineNumber":181,"sourceCode":"// piece of multi-step work reaches it.\nconst maxToolRounds = 12\n\nfunc (p *Provider) Stream(ctx context.Context, req *ai.Request, opts ...ai.GenerateOption) (ai.Stream, error) {\n\tapiReq := map[string]any{\n\t\t\"contents\": geminiContents(req),\n\t}\n\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()","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/gemini/gemini.go#L163-L199","documentation":"Gemini provider's Stream method failed to json.Marshal the assembled request map into the HTTP body. Marshal errors on map[string]any are rare and indicate values that are not JSON-encodable (channels, funcs, unsupported types) sneaked into the request construction. The wrapped error identifies the offending value.","triggerScenarios":"Calling Stream when the internally-built apiReq map contains a value json.Marshal cannot encode (e.g. a non-marshalable type inserted via options or prompt content).","commonSituations":"Passing custom types implementing MarshalJSON incorrectly through prompt/options plumbing; embedding channel/func values via configuration; a code regression in request construction.","solutions":["Inspect the wrapped %w error to identify the non-marshalable value and fix where it enters the request.","Ensure all option/prompt values passed to the provider are plain JSON-safe types (string, number, bool, slice, map, struct).","Upgrade the library version if this occurs with standard usage, as it likely indicates an internal regression.","Marshal a copy of the request yourself before calling Stream to isolate the bad value."],"exampleFix":"// before\napiReq[\"contents\"] = myCustomContent\n// after\nb, err := json.Marshal(myCustomContent)\nif err != nil {\n    return nil, fmt.Errorf(\"unsupported content type: %w\", err)\n}\nvar safe any\njson.Unmarshal(b, &safe)\napiReq[\"contents\"] = safe","handlingStrategy":"validation","validationCode":"if _, err := json.Marshal(req); err != nil {\n    return fmt.Errorf(\"request not JSON-serializable: %w\", err)\n}","typeGuard":"func isJSONSafe(v any) bool {\n    b, err := json.Marshal(v)\n    return err == nil && json.Valid(b)\n}","tryCatchPattern":"stream, err := provider.Stream(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to marshal stream request\") {\n        return fmt.Errorf(\"client bug: non-serializable value in request: %w\", err)\n    }\n    return err\n}","preventionTips":["Pass only plain JSON types (string/number/bool/slice/map) into provider options and messages","Round-trip custom content types through json.Marshal before handing them to the provider","Add a startup smoke test that marshals a representative request"],"tags":["json","marshal","gemini","streaming"],"backgroundTag":"json-marshal-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}