Skip to content

Conversation

@yeonjaee
Copy link

@yeonjaee yeonjaee commented Dec 24, 2025

Description

I'd like to report a potential issue with stream error handling in getResponseStream that may cause server runtime crashes, and propose a possible fix. I'm not entirely certain about the root cause, so I would appreciate the maintainers' review and feedback on this approach.

Environment

  • Runtime: Node.js
  • Node.js version: v22.17.0
  • Genkit version: 1.27.0
  • @genkit-ai/google-genai version: 1.27.0

Issue Observed

We occasionally encountered unhandled rejections that crashed our server runtime. After investigation, I suspect the issue originates from controller.error() calls in the getResponseStream function, particularly when the "Failed to parse stream" error occurs.

Suspected scenarios:

  1. Stream ends with unparsed text (e.g., [DONE] markers, incomplete SSE data like data: )
  2. controller.error(new Error('Failed to parse stream')) is called (line 348)
  3. This puts the ReadableStream into an error state
  4. When stream consumers, call reader.read(), it returns a rejected Promise
  5. Without try-catch blocks, these rejected Promises propagate uncaught through the async call chain.
  6. This results in an unhandled Promise rejection
  7. Node.js terminates the process (default behavior for unhandled rejections)

Proposed Solution

Add error handling in the stream consumers to catch and properly handle errors from controller.error():

Checklist (if applicable):

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @yeonjaee, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces crucial error handling mechanisms within the google-genai plugin to prevent server instability caused by unhandled stream errors. By implementing try-catch-finally blocks around stream reading operations, the changes ensure that potential issues like 'Failed to parse stream' errors are gracefully managed, thereby enhancing the robustness and reliability of the application when interacting with generative AI streams.

Highlights

  • Prevent Server Crashes: This pull request addresses a critical issue where unhandled stream errors in the google-genai plugin could lead to server runtime crashes due to unhandled Promise rejections.
  • Robust Stream Error Handling: Error handling has been implemented in the generateResponseSequence and getResponsePromise functions by wrapping stream consumption logic in try...catch...finally blocks.
  • Resource Management: The finally blocks in both modified functions now ensure that reader.releaseLock() is consistently called, preventing resource leaks.
  • Partial Response Recovery: In getResponsePromise, if a stream error occurs after some responses have already been received, the function will now aggregate and return the partial responses instead of re-throwing the error, improving resilience.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Thank you for this contribution. Your detailed analysis of the unhandled promise rejection issue is excellent, and the proposed fix correctly addresses the problem by adding try...catch...finally blocks to handle stream errors and ensure resources are released. This will prevent the server crashes you've observed. I have a couple of suggestions for minor improvements. In generateResponseSequence, the catch block is redundant and can be removed for conciseness. In getResponsePromise, while returning partial data on error is a good strategy, the error is currently swallowed, which could make debugging difficult for users of this library. I've suggested logging the error to provide more visibility. Overall, this is a valuable fix that improves the robustness of stream handling. Well done!

Comment on lines +405 to 409
} catch (error) {
throw error;
} finally {
reader.releaseLock();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This catch block is redundant as it just re-throws the error. An error thrown within the try block will propagate automatically from the async generator. You can simplify the code by removing the catch block.

  } finally {
    reader.releaseLock();
  }

}
} catch (error) {
if (allResponses.length) {
return aggregateResponses(allResponses);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While returning a partial response on stream error is a reasonable strategy, the original error is completely swallowed here. This can make debugging difficult for the library user, as they would receive an incomplete response without any indication of what went wrong. Consider logging the error before returning the aggregated responses to provide visibility into the underlying issue. For example:

// Inside the catch block
if (allResponses.length) {
  console.error('Stream processing failed. Returning partial response. Error:', error);
  return aggregateResponses(allResponses);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant