Skip to content

Commit 03b5f06

Browse files
cyphercodesdaniel-sanche
authored andcommitted
fix(api-core): handle list-shaped REST error payloads (#18232)
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/google-cloud-python/issues) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [x] Code coverage does not decrease (if any source code was changed) - [x] Appropriate docs were updated (if necessary; no docs change needed for this bug fix) Fixes #18223 🦕 ## Summary - Normalize list-shaped REST error payloads to the first dict item before reading the standard `error` object. - Preserve existing dict payload behavior and fall back to `unknown error` when no dict item is present. - Add unit coverage for list-wrapped error payloads. ## Tests - `pytest -q tests/unit/test_exceptions.py -k 'http_response or error_details_from_rest_response'` - `pytest -q tests/unit/test_exceptions.py` - `ruff format --check --target-version=py310 --line-length=88 google/api_core/exceptions.py tests/unit/test_exceptions.py` - `flake8 google/api_core/exceptions.py tests/unit/test_exceptions.py` - `git diff --check` ## CLA Google CLA is required by the repository; awaiting the repository's CLA check on this PR. Co-authored-by: cyphercodes <cyphercodes@users.noreply.github.com>
1 parent a4b442b commit 03b5f06

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

packages/google-api-core/google/api_core/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ def format_http_response_error(
510510
:class:`GoogleAPICallError`, with the message and errors populated
511511
from the response.
512512
"""
513+
if isinstance(payload, list):
514+
payload = next((item for item in payload if isinstance(item, dict)), {})
513515
payload = {} if not payload else payload
514516
error_message = payload.get("error", {}).get("message", "unknown error")
515517
errors = payload.get("error", {}).get("errors", ())

packages/google-api-core/tests/unit/test_exceptions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,31 @@ def test_from_http_response_json_content():
132132
assert exception.errors == ["1", "2"]
133133

134134

135+
def test_from_http_response_json_list_content():
136+
response = make_response(
137+
json.dumps(
138+
[{"error": {"message": "json message", "errors": ["1", "2"]}}]
139+
).encode("utf-8")
140+
)
141+
142+
exception = exceptions.from_http_response(response)
143+
144+
assert isinstance(exception, exceptions.NotFound)
145+
assert exception.code == http.client.NOT_FOUND
146+
assert exception.message == "POST https://example.com/: json message"
147+
assert exception.errors == ["1", "2"]
148+
149+
150+
def test_from_http_response_json_list_content_without_error_dict():
151+
response = make_response(json.dumps(["error message"]).encode("utf-8"))
152+
153+
exception = exceptions.from_http_response(response)
154+
155+
assert isinstance(exception, exceptions.NotFound)
156+
assert exception.code == http.client.NOT_FOUND
157+
assert exception.message == "POST https://example.com/: unknown error"
158+
159+
135160
def test_from_http_response_bad_json_content():
136161
response = make_response(json.dumps({"meep": "moop"}).encode("utf-8"))
137162

0 commit comments

Comments
 (0)