Symptom
IChatClient.GetStreamingResponseAsync on GeminiClient (Google_Gemini 0.11.2) completes without yielding a single TextContent against the live API, while GetResponseAsync answers the same prompt normally. Observed 2026-09-15 from a production backend: every streamed call ended with an empty aggregate (gemini returned an empty response), model gemini-3.5-flash-lite, plain-text prompt, ThinkingLevel = Minimal via RawRepresentationFactory.
Root cause (from the generated code)
Google.Gemini.GeminiClient.ModelsStreamGenerateContentAsStream.g.cs builds the request as
var __pathBuilder = new PathBuilder(path: $"/models/{modelsId}:streamGenerateContent", baseUri: HttpClient.BaseAddress);
// … only the ApiKey query authorization is appended …
and then reads the body with
await foreach (var __sseEvent in System.Net.ServerSentEvents.SseParser.Create(__stream).EnumerateAsync(...))
The Gemini REST API only answers streamGenerateContent as server-sent events when ?alt=sse is on the query string. Without it the response is a chunked JSON array of GenerateContentResponse objects ([{…},\r\n{…}]), which contains no data: lines, so SseParser enumerates zero events and the method returns having yielded nothing — no exception, no text.
Nothing in the repo adds the parameter: GeminiClient.ChatClient.cs calls ModelsStreamGenerateContentAsStreamAsync(modelsId, request, cancellationToken) with no requestOptions, and src/libs/Google.Gemini/openapi.json / convert_discovery.py do not declare alt on the stream operations. (Dynamic… and TunedModels…StreamGenerateContentAsStreamAsync have the same shape.)
Reference: https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent — "alt=sse … streams the response as server-sent events".
Fix options
- Cheapest, in the SDK: have the three
…StreamGenerateContentAsStreamAsync requests always carry alt=sse — e.g. PrepareModelsStreamGenerateContentAsStreamArguments partial, or the ChatClient extension passing requestOptions: new AutoSDKRequestOptions { QueryParameters = { ["alt"] = "sse" } }.
- In the spec: declare
alt as a query parameter with default sse on the :streamGenerateContent operations in openapi.json (via convert_discovery.py), so the generator emits it.
- Alternatively, fall back to parsing the JSON-array form when the response
Content-Type is application/json.
Either way, src/tests/IntegrationTests/Examples/ChatClient.FiveRandomWords.Streaming.cs would have caught this if it ran against the live API — worth asserting updates.Any(u => u.Text.Length > 0) there.
Consumer-side workaround
A separate GeminiClient with Options.QueryParameters["alt"] = "sse" used only for streaming calls. Tracking on our side: HavenDV/Advantage (linked below).
Symptom
IChatClient.GetStreamingResponseAsynconGeminiClient(Google_Gemini 0.11.2) completes without yielding a singleTextContentagainst the live API, whileGetResponseAsyncanswers the same prompt normally. Observed 2026-09-15 from a production backend: every streamed call ended with an empty aggregate (gemini returned an empty response), modelgemini-3.5-flash-lite, plain-text prompt,ThinkingLevel = MinimalviaRawRepresentationFactory.Root cause (from the generated code)
Google.Gemini.GeminiClient.ModelsStreamGenerateContentAsStream.g.csbuilds the request asand then reads the body with
The Gemini REST API only answers
streamGenerateContentas server-sent events when?alt=sseis on the query string. Without it the response is a chunked JSON array ofGenerateContentResponseobjects ([{…},\r\n{…}]), which contains nodata:lines, soSseParserenumerates zero events and the method returns having yielded nothing — no exception, no text.Nothing in the repo adds the parameter:
GeminiClient.ChatClient.cscallsModelsStreamGenerateContentAsStreamAsync(modelsId, request, cancellationToken)with norequestOptions, andsrc/libs/Google.Gemini/openapi.json/convert_discovery.pydo not declarealton the stream operations. (Dynamic…andTunedModels…StreamGenerateContentAsStreamAsynchave the same shape.)Reference: https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent — "
alt=sse… streams the response as server-sent events".Fix options
…StreamGenerateContentAsStreamAsyncrequests always carryalt=sse— e.g.PrepareModelsStreamGenerateContentAsStreamArgumentspartial, or the ChatClient extension passingrequestOptions: new AutoSDKRequestOptions { QueryParameters = { ["alt"] = "sse" } }.altas a query parameter with defaultsseon the:streamGenerateContentoperations inopenapi.json(viaconvert_discovery.py), so the generator emits it.Content-Typeisapplication/json.Either way,
src/tests/IntegrationTests/Examples/ChatClient.FiveRandomWords.Streaming.cswould have caught this if it ran against the live API — worth assertingupdates.Any(u => u.Text.Length > 0)there.Consumer-side workaround
A separate
GeminiClientwithOptions.QueryParameters["alt"] = "sse"used only for streaming calls. Tracking on our side: HavenDV/Advantage (linked below).