tryAGI / tryAGI/Google_Generative_AI
IChatClient.GetStreamingResponseAsync yields nothing: streamGenerateContent is requested without ?alt=sse but parsed as SSE
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 9
- Forks
- 1
- Avg merge
- 1m
- Merged PRs (30d)
- 79
Description
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
…StreamGenerateContentAsStreamAsyncrequests always carryalt=sse— e.g.PrepareModelsStreamGenerateContentAsStreamArgumentspartial, or the ChatClient extension passingrequestOptions: new AutoSDKRequestOptions { QueryParameters = { ["alt"] = "sse" } }. - In the spec: declare
altas a query parameter with defaultsseon the:streamGenerateContentoperations inopenapi.json(viaconvert_discovery.py), so the generator emits it. - Alternatively, fall back to parsing the JSON-array form when the response
Content-Typeisapplication/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).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Google.Gemini.GeminiClient.ModelsStreamGenerateContentAsStream.g.cs, GeminiClient.ChatClient.cs, and the stream operation definitions in src/libs/Google.Gemini/openapi.json and convert_discovery.py. Compare the request query parameters with the API's streaming requirements, then run src/tests/IntegrationTests/Examples/ChatClient.FiveRandomWords.Streaming.cs against the live API. Done means streaming yields non-empty text updates for the affected stream operations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, openapi
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100