-
Notifications
You must be signed in to change notification settings - Fork 623
Description
Describe the bug
When using the Google AI plugin for streaming generation with structured output and ThinkingConfig, the application panics with:
panic: runtime error: index out of range [0] with length 0
Stack trace:
github.com/firebase/genkit/go/plugins/googlegenai.generate-range1(...)
github.com/firebase/genkit/go@v1.1.0/plugins/googlegenai/gemini.go:315
Root cause:
In gemini.go lines 303-315, there's an index variable misuse:
for i, c := range chunk.Candidates {
tc, err := translateCandidate(c)
// ...
chunks = append(chunks, c.Content.Parts[i]) // Bug: i is Candidates index, not Parts index
}The variable i represents the index in the Candidates array, but the code uses it to access c.Content.Parts[i], which is unrelated. This causes a panic when:
c.Content.Partsis empty (length 0) buti=0(first candidate)c.Content.Partshas fewer elements than the Candidates array
To Reproduce
I've created a minimal reproduction case that triggers this bug with approximately 50% success rate.
Code:
package main
import (
"context"
"fmt"
"os"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))
// Run multiple rapid requests to increase panic probability
for i := 0; i < 10; i++ {
testCase(ctx, g)
}
}
func testCase(ctx context.Context, g *genkit.Genkit) error {
type Output struct {
Text string `json:"text"`
}
_, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithPrompt("Hi"),
ai.WithConfig(&genai.GenerateContentConfig{
ThinkingConfig: &genai.ThinkingConfig{
ThinkingBudget: genai.Ptr(int32(0)),
},
}),
ai.WithOutputType(Output{}),
ai.WithStreaming(func(ctx context.Context, chunk *ai.ModelResponseChunk) error {
return nil
}),
)
return err
}How to run:
- Set
GOOGLE_API_KEYenvironment variable - Run the code multiple times (bug is intermittent)
- Panic typically occurs during rapid consecutive requests
Reproduction rate: Approximately 50% (observed 1 panic in 2 complete executions)
Expected behavior
The streaming callback should handle all Gemini API response structures gracefully, including chunks with empty Parts arrays, without panicking.
Screenshots
N/A
Runtime (please complete the following information):
- Operating system: macOS
- OS version: Darwin 24.6.0
Go version:
go version go1.25.2 darwin/arm64
Additional context
Proposed Fix:
Replace lines 303-315 in gemini.go with:
for _, c := range chunk.Candidates {
tc, err := translateCandidate(c)
if err != nil {
return nil, err
}
err = cb(ctx, &ai.ModelResponseChunk{
Content: tc.Message.Content,
})
if err != nil {
return nil, err
}
// Safely iterate through all parts
for _, part := range c.Content.Parts {
chunks = append(chunks, part)
}
}Key changes:
- Remove index variable
i - Use nested loop to safely iterate all Parts
- Handles empty Parts arrays correctly
- Correctly handles multiple candidates
Related Issues:
A similar bug in tool usage was fixed in PR #2980 (related to issue #2978), but this streaming bug remains.
Thank you for maintaining this excellent project. Happy to provide additional information or submit a PR if helpful.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status