Skip to content

Conversation

DavidLee528
Copy link

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 incorrect Content-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:

    • 401 / 404 / 500 / 503 HTTP errors
    • Incorrect Content-Type
    • Normal streaming success cases
  • 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.

@DavidLee528 DavidLee528 requested a review from a team as a code owner October 14, 2025 10:07
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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

  • Enhanced HTTP Error Reporting: The A2AClientHTTPError now captures and exposes more detailed information, including the HTTP status, message, raw response body, and headers, providing richer context for debugging streaming errors.
  • Pre-SSE Parsing Validation: Streaming responses are now validated before Server-Sent Events (SSE) parsing begins. This prevents misleading SSE protocol errors by immediately raising an A2AClientHTTPError if the HTTP status is not 2xx or if the Content-Type header is incorrect.
  • Unified Error Handling for Streaming Transports: Both REST and JSON-RPC streaming transports have been updated to utilize a new shared utility for consistent and robust error handling, ensuring all streaming clients benefit from the improved error surfacing.
  • Comprehensive Test Coverage: Extensive new tests have been added to cover various error scenarios, including 401, 404, 500, and 503 HTTP errors, incorrect Content-Type responses, and to confirm the continued correct behavior of normal streaming success cases.
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

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.

Comment on lines +35 to +38
try:
json_payload = response.json()
except (json.JSONDecodeError, ValueError):
json_payload = None
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

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.

Suggested change
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

Comment on lines +15 to +35
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}')
Copy link
Contributor

Choose a reason for hiding this comment

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

low

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.

Suggested change
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}')

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: A2A Client incorrectly handles HTTP error responses when using streaming mode

1 participant