From 0100a770738aea8c0502845ff4de1aabf8e7d02f Mon Sep 17 00:00:00 2001 From: Arima Gupta Date: Fri, 3 Jul 2026 14:25:21 +0530 Subject: [PATCH] fix(api_core): clarify misleading http 404 unimplemented error message --- .../google/api_core/exceptions.py | 18 ++++++++++++++---- .../tests/unit/test_exceptions.py | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/google-api-core/google/api_core/exceptions.py b/packages/google-api-core/google/api_core/exceptions.py index e17fa1d8d137..71ceb759b2fc 100644 --- a/packages/google-api-core/google/api_core/exceptions.py +++ b/packages/google-api-core/google/api_core/exceptions.py @@ -18,12 +18,11 @@ on :mod:`google.api_core`, including both HTTP and gRPC clients. """ -from __future__ import absolute_import -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals import http.client -from typing import Optional, Dict import warnings +from typing import Dict, Optional from google.rpc import error_details_pb2 @@ -657,9 +656,20 @@ def from_grpc_error(rpc_exc): grpc is not None and isinstance(rpc_exc, grpc.Call) ) or _is_informative_grpc_error(rpc_exc): details, err_info = _parse_grpc_error_details(rpc_exc) + message = rpc_exc.details() + if ( + grpc is not None + and rpc_exc.code() == grpc.StatusCode.UNIMPLEMENTED + and "Received http2 header with status: 404" in message + ): + message = ( + f"{message}. This usually indicates that the 'api_endpoint' " + "configuration in ClientOptions is incorrect, contains a typo, " + "or is an invalid regional endpoint for this service." + ) return from_grpc_status( rpc_exc.code(), - rpc_exc.details(), + message, errors=(rpc_exc,), details=details, response=rpc_exc, diff --git a/packages/google-api-core/tests/unit/test_exceptions.py b/packages/google-api-core/tests/unit/test_exceptions.py index e3f8f909a07c..c7171204d093 100644 --- a/packages/google-api-core/tests/unit/test_exceptions.py +++ b/packages/google-api-core/tests/unit/test_exceptions.py @@ -25,10 +25,11 @@ except ImportError: # pragma: NO COVER grpc = rpc_status = None -from google.api_core import exceptions from google.protobuf import any_pb2, json_format from google.rpc import error_details_pb2, status_pb2 +from google.api_core import exceptions + def test_create_google_cloud_error(): exception = exceptions.GoogleAPICallError("Testing") @@ -393,3 +394,18 @@ def test_error_details_from_grpc_response_unknown_error(): and exception.domain is None and exception.metadata is None ) + + +@pytest.mark.skipif(grpc is None, reason="No grpc") +def test_from_grpc_error_misleading_404(): + message = "Received http2 header with status: 404" + error = mock.create_autospec(grpc.Call, instance=True) + error.code.return_value = grpc.StatusCode.UNIMPLEMENTED + error.details.return_value = message + + exception = exceptions.from_grpc_error(error) + + assert isinstance(exception, exceptions.MethodNotImplemented) + assert exception.grpc_status_code == grpc.StatusCode.UNIMPLEMENTED + assert "Received http2 header with status: 404" in exception.message + assert "api_endpoint" in exception.message