Skip to content

fix(messaging): preserve per-message results in send_each_async - #1006

Open
EnesKartal wants to merge 1 commit into
firebase:mainfrom
EnesKartal:fix/send-each-async-preserve-results
Open

EnesKartal wants to merge 1 commit into
firebase:mainfrom
EnesKartal:fix/send-each-async-preserve-results

Conversation

@EnesKartal

Copy link
Copy Markdown

Fixes #995.

  • Catches unexpected non-httpx.HTTPError / non-RequestException exceptions (such as KeyError(stream_id) from httpcore HTTP/2 transport errors) inside send_data() in send_each_async and wraps them in SendResponse(resp=None, exception=exceptions.UnknownError(...)).
  • Prevents a single per-message transport/parsing exception from aborting asyncio.gather() and losing the per-message SendResponse results of all other messages in the batch.
  • Adds test_send_each_async_unexpected_exception_preserves_other_results in tests/test_messaging.py.

@EnesKartal
EnesKartal requested a review from a team November 14, 2026 21:49
@google-cla

google-cla Bot commented Nov 14, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

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

Copy link
Copy Markdown

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 adds generic exception handling to send_data in firebase_admin/messaging.py to catch unexpected exceptions during remote service calls and wrap them in exceptions.UnknownError, along with a corresponding unit test. The review feedback points out that resp.json() is called outside of the try-except block, which could still raise an unhandled exception if the response contains invalid JSON. It is recommended to wrap this call in a try-except block as well to ensure robust error handling.

Comment on lines +603 to 611
except Exception as exception:
return SendResponse(
resp=None,
exception=exceptions.UnknownError(
message=f'Unknown error while making remote service calls: {exception}',
cause=exception,
),
)
return SendResponse(resp.json(), exception=None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

While catching unexpected exceptions during the remote call is a great improvement, calling resp.json() at line 611 is currently outside of any try-except block. If the response body is empty or contains invalid JSON, resp.json() will raise a ValueError (or JSONDecodeError), which will propagate up and abort the entire asyncio.gather() call, losing all other successful results in the batch.\n\nTo prevent this, we should wrap the resp.json() call in a try-except block as well, wrapping any parsing exceptions in an UnknownError to preserve the other results.

            except Exception as exception:\n                return SendResponse(\n                    resp=None,\n                    exception=exceptions.UnknownError(\n                        message=f'Unknown error while making remote service calls: {exception}',\n                        cause=exception,\n                    ),\n                )\n            try:\n                return SendResponse(resp.json(), exception=None)\n            except Exception as exception:\n                return SendResponse(\n                    resp=None,\n                    exception=exceptions.UnknownError(\n                        message=f'Unknown error while parsing remote service response: {exception}',\n                        cause=exception,\n                    ),\n                )

This branch has not been deployed

No deployments
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.

send_each_async loses all per-message results after numeric HTTP/2 transport error

1 participant