Skip to content

Streaming with HTTPOptions.Timeout drops all chunks after the first #689

@adek05

Description

@adek05

Environment details

  • Programming language: Go
  • OS: Linux (also reproducible on macOS)
  • Language runtime version: go 1.24.4
  • Package version: google.golang.org/genai v1.42.0

Steps to reproduce

  1. Create a client with HTTPOptions.Timeout set:
timeout := 5 * time.Minute
client, _ := genai.NewClient(ctx, &genai.ClientConfig{
    Backend:     genai.BackendVertexAI,
    Credentials: creds,
    HTTPOptions: genai.HTTPOptions{Timeout: &timeout},
})
  1. Make a streaming request:
chat, _ := client.Chats.Create(ctx, "gemini-2.0-flash", config, nil)
count := 0
for chunk, err := range chat.SendMessageStream(ctx, genai.Part{Text: "Write a long poem"}) {
    if err != nil { log.Fatal(err) }
    count++
}
fmt.Println(count) // prints 1, expected 3-5+
  1. Remove the timeout — all chunks arrive correctly.

Demonstrated by the test attached to #688

Root cause

In api_client.go, sendStreamRequest creates a timeout context and immediately defers cancel:

requestContext, cancel = context.WithTimeout(ctx, *timeout)
defer cancel()

sendStreamRequest returns after setting up the bufio.Scanner but before iterateResponseStream consumes any chunks. The deferred cancel() fires on return, killing the HTTP connection. The first chunk may be buffered so it succeeds, but subsequent Scan() calls fail with "context canceled".

Suggested fix

Transfer ownership of cancel from sendStreamRequest's defer to responseStream, and call it in iterateResponseStream's cleanup defer alongside resp.Body.Close(). I have a PR with this fix and a regression test: #688

Metadata

Metadata

Labels

api:gemini-apiIssues related to Gemini APIpriority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions