@@ -276,7 +276,10 @@ func generate(
276276 if err != nil {
277277 return nil , err
278278 }
279- r := translateResponse (resp )
279+ r , err := translateResponse (resp )
280+ if err != nil {
281+ return nil , err
282+ }
280283
281284 r .Request = input
282285 if cache != nil {
@@ -298,8 +301,11 @@ func generate(
298301 return nil , err
299302 }
300303 for i , c := range chunk .Candidates {
301- tc := translateCandidate (c )
302- err := cb (ctx , & ai.ModelResponseChunk {
304+ tc , err := translateCandidate (c )
305+ if err != nil {
306+ return nil , err
307+ }
308+ err = cb (ctx , & ai.ModelResponseChunk {
303309 Content : tc .Message .Content ,
304310 })
305311 if err != nil {
@@ -322,7 +328,10 @@ func generate(
322328 },
323329 }
324330 resp .Candidates = merged
325- r = translateResponse (resp )
331+ r , err = translateResponse (resp )
332+ if err != nil {
333+ return nil , fmt .Errorf ("failed to generate contents: %w" , err )
334+ }
326335 r .Request = input
327336 if cache != nil {
328337 r .Message .Metadata = cacheMetadata (r .Message .Metadata , cache )
@@ -339,11 +348,17 @@ func toGeminiRequest(input *ai.ModelRequest, cache *genai.CachedContent) (*genai
339348 return nil , err
340349 }
341350
342- // only one candidate is supported by default
343- gcc .CandidateCount = 1
351+ // candidate count might not be set to 1 and will keep its zero value if not set
352+ // e.g. default value from reflection server is 0
353+ if gcc .CandidateCount == 0 {
354+ gcc .CandidateCount = 1
355+ }
344356
345357 // Genkit primitive fields must be used instead of go-genai fields
346358 // i.e.: system prompt, tools, cached content, response schema, etc
359+ if gcc .CandidateCount != 1 {
360+ return nil , errors .New ("multiple candidates is not supported" )
361+ }
347362 if gcc .SystemInstruction != nil {
348363 return nil , errors .New ("system instruction must be set using Genkit feature: ai.WithSystemPrompt()" )
349364 }
@@ -657,7 +672,7 @@ func toGeminiToolChoice(toolChoice ai.ToolChoice, tools []*ai.ToolDefinition) (*
657672}
658673
659674// translateCandidate translates from a genai.GenerateContentResponse to an ai.ModelResponse.
660- func translateCandidate (cand * genai.Candidate ) * ai.ModelResponse {
675+ func translateCandidate (cand * genai.Candidate ) ( * ai.ModelResponse , error ) {
661676 m := & ai.ModelResponse {}
662677 switch cand .FinishReason {
663678 case genai .FinishReasonStop :
@@ -673,6 +688,10 @@ func translateCandidate(cand *genai.Candidate) *ai.ModelResponse {
673688 default : // Unspecified
674689 m .FinishReason = ai .FinishReasonUnknown
675690 }
691+
692+ if cand .Content == nil {
693+ return nil , fmt .Errorf ("no valid candidates were found in the generate response" )
694+ }
676695 msg := & ai.Message {}
677696 msg .Role = ai .Role (cand .Content .Role )
678697
@@ -729,14 +748,19 @@ func translateCandidate(cand *genai.Candidate) *ai.ModelResponse {
729748 msg .Content = append (msg .Content , p )
730749 }
731750 m .Message = msg
732- return m
751+ return m , nil
733752}
734753
735754// Translate from a genai.GenerateContentResponse to a ai.ModelResponse.
736- func translateResponse (resp * genai.GenerateContentResponse ) * ai.ModelResponse {
755+ func translateResponse (resp * genai.GenerateContentResponse ) ( * ai.ModelResponse , error ) {
737756 var r * ai.ModelResponse
757+ var err error
758+
738759 if len (resp .Candidates ) > 0 {
739- r = translateCandidate (resp .Candidates [0 ])
760+ r , err = translateCandidate (resp .Candidates [0 ])
761+ if err != nil {
762+ return nil , err
763+ }
740764 } else {
741765 r = & ai.ModelResponse {}
742766 }
@@ -752,7 +776,7 @@ func translateResponse(resp *genai.GenerateContentResponse) *ai.ModelResponse {
752776 r .Usage .CachedContentTokens = int (u .CachedContentTokenCount )
753777 r .Usage .ThoughtsTokens = int (u .ThoughtsTokenCount )
754778 }
755- return r
779+ return r , nil
756780}
757781
758782// toGeminiParts converts a slice of [ai.Part] to a slice of [genai.Part].
0 commit comments