-
Notifications
You must be signed in to change notification settings - Fork 260
fix(client): surface real HTTP status & message for streaming errors; avoid SSE parse on non-2xx #505
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?
Conversation
Summary of ChangesHello @DavidLee528, 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 significantly improves the client's ability to handle and report errors during streaming operations. By introducing a more informative HTTP error class and implementing pre-parsing validation, it ensures that users receive accurate and actionable feedback when server-side issues or malformed responses occur, rather than generic streaming protocol failures. This directly addresses an existing issue where streaming clients would report misleading SSE errors. Highlights
Using Gemini Code AssistThe 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
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 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
|
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.
Code Review
This pull request does a great job of improving error handling for streaming responses by introducing a more informative A2AClientHTTPError
and validating responses before attempting to parse them as Server-Sent Events. The new _streaming_utils.py
module centralizes this logic effectively, and the comprehensive new tests ensure these changes are robust.
I have a couple of minor suggestions to improve consistency and clarity in the new error handling code. Overall, this is a solid improvement that will make debugging streaming issues much easier.
try: | ||
json_payload = response.json() | ||
except (json.JSONDecodeError, ValueError): | ||
json_payload = None |
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 response body is already read into the body_text
variable. Instead of calling response.json()
, which might re-process the response body, it's more direct and potentially more efficient to parse body_text
directly. This also makes the flow of data clearer.
try: | |
json_payload = response.json() | |
except (json.JSONDecodeError, ValueError): | |
json_payload = None | |
try: | |
json_payload = json.loads(body_text) if body_text else None | |
except json.JSONDecodeError: | |
json_payload = None |
def __init__( | ||
self, | ||
status: int, | ||
message: str, | ||
body: str | None = None, | ||
headers: Mapping[str, str] | None = None, | ||
): | ||
"""Initializes the A2AClientHTTPError. | ||
Args: | ||
status_code: The HTTP status code of the response. | ||
status: The HTTP status code of the response. | ||
message: A descriptive error message. | ||
body: The raw response body, if available. | ||
headers: The HTTP response headers. | ||
""" | ||
self.status_code = status_code | ||
self.status = status | ||
self.status_code = status | ||
self.message = message | ||
super().__init__(f'HTTP Error {status_code}: {message}') | ||
self.body = body | ||
self.headers = dict(headers or {}) | ||
super().__init__(f'HTTP {status} - {message}') |
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.
For consistency and to avoid redundancy, it would be clearer to use a single attribute for the status code. The httpx
library uses status_code
, which is a common convention. Using both status
and status_code
for the same value can be confusing. I suggest standardizing on status_code
.
def __init__( | |
self, | |
status: int, | |
message: str, | |
body: str | None = None, | |
headers: Mapping[str, str] | None = None, | |
): | |
"""Initializes the A2AClientHTTPError. | |
Args: | |
status_code: The HTTP status code of the response. | |
status: The HTTP status code of the response. | |
message: A descriptive error message. | |
body: The raw response body, if available. | |
headers: The HTTP response headers. | |
""" | |
self.status_code = status_code | |
self.status = status | |
self.status_code = status | |
self.message = message | |
super().__init__(f'HTTP Error {status_code}: {message}') | |
self.body = body | |
self.headers = dict(headers or {}) | |
super().__init__(f'HTTP {status} - {message}') | |
def __init__( | |
self, | |
status_code: int, | |
message: str, | |
body: str | None = None, | |
headers: Mapping[str, str] | None = None, | |
): | |
"""Initializes the A2AClientHTTPError. | |
Args: | |
status_code: The HTTP status code of the response. | |
message: A descriptive error message. | |
body: The raw response body, if available. | |
headers: The HTTP response headers. | |
""" | |
self.status_code = status_code | |
self.message = message | |
self.body = body | |
self.headers = dict(headers or {}) | |
super().__init__(f'HTTP {status_code} - {message}') |
Description
Introduce a richer
A2AClientHTTPError
to include the real status, message, body, and headers, ensuring clearer feedback to streaming callers.Validate streaming responses before SSE parsing — raise
A2AClientHTTPError
on any non-2xx status or incorrectContent-Type
.Update REST and JSON-RPC streaming transports to use the new error-handling helper, maintaining existing SSE parsing on the valid (2xx) path.
Add comprehensive tests for:
Content-Type
Align and expand error-handling test coverage with dedicated streaming tests.
Result:
Resolves #502 by ensuring streaming clients correctly surface the server’s actual HTTP error payload and status, instead of reporting misleading SSE protocol errors.