-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix: handle empty responses from Gemini API #7047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl | |
|
||
let lastUsageMetadata: GenerateContentResponseUsageMetadata | undefined | ||
let pendingGroundingMetadata: GroundingMetadata | undefined | ||
let hasYieldedContent = false // Track if we've yielded any text content | ||
|
||
for await (const chunk of result) { | ||
// Process candidates and their parts to separate thoughts from content | ||
|
@@ -115,6 +116,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl | |
// This is regular content | ||
if (part.text) { | ||
yield { type: "text", text: part.text } | ||
hasYieldedContent = true | ||
} | ||
} | ||
} | ||
|
@@ -124,13 +126,27 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl | |
// Fallback to the original text property if no candidates structure | ||
else if (chunk.text) { | ||
yield { type: "text", text: chunk.text } | ||
hasYieldedContent = true | ||
} | ||
|
||
if (chunk.usageMetadata) { | ||
lastUsageMetadata = chunk.usageMetadata | ||
} | ||
} | ||
|
||
// Check if we got an empty response | ||
if (!hasYieldedContent) { | ||
// Log the issue for debugging | ||
console.warn("Gemini API returned empty response, no text content was generated") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is |
||
|
||
// Throw a specific error that can be caught and retried | ||
throw new Error( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice we're throwing an error with |
||
t("common:errors.gemini.empty_response", { | ||
error: "The Gemini API did not return any text content. This may be a temporary issue.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message includes both a translated message and a hardcoded English fallback. Could we simplify this by ensuring all necessary context is in the translation files themselves, avoiding the redundancy? |
||
}), | ||
) | ||
} | ||
|
||
if (pendingGroundingMetadata) { | ||
const citations = this.extractCitationsOnly(pendingGroundingMetadata) | ||
if (citations) { | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test expects
t("common:errors.gemini.generate_stream")
but the actual error thrown ist("common:errors.gemini.empty_response")
. While this works due to the error wrapping in the catch block, would it be clearer to test for the specific empty response error message to make the test's intent more obvious?