Repository navigation
Uploading conversions async - AttributeError: 'UnaryUnaryCall' object has no attribute 'exception' #1059
Description
Describe the bug:
Sometimes upload_click_conversions async call (from the client.get_service('ConversionUploadService', is_async=True)) failed with the AttributeError: 'UnaryUnaryCall' object has no attribute 'exception'
Steps to Reproduce:
Unable to reproduce locally, encountered this issue only in production (15 errors per 77k successful requests). Looks like this happens on timeouts or google ads service temporary unavailability
Expected behavior:
No error or some error specific to Google Ads, not generic AttributeError
Client library version and API version:
Client library version: 29.1.0
Google Ads API version: v23
Python version: 3.12
Python deps (all the deps from the project):
aiohttp==3.9.5
aiosignal==1.4.0
annotated-types==0.7.0
anyio==4.6.0
attrs==25.4.0
CacheControl==0.14.4
certifi==2026.2.25
cffi==2.0.0
charset-normalizer==3.4.4
click==8.3.1
cryptography==46.0.5
dnspython==2.8.0
email_validator==2.2.0
facade-webonboarding-proto==0.0.224
fastapi==0.115.0
firebase-admin==6.0.0
frozenlist==1.8.0
google-ads==29.1.0
google-api-core==2.29.0
google-api-python-client==2.190.0
google-auth==2.48.0
google-auth-httplib2==0.3.0
google-auth-oauthlib==1.3.0
google-cloud-core==2.5.0
google-cloud-firestore==2.23.0
google-cloud-storage==3.9.0
google-crc32c==1.8.0
google-resumable-media==2.8.0
googleapis-common-protos==1.72.0
grpc-gateway-protoc-gen-openapiv2==0.1.0
grpcio==1.62.3
grpcio-status==1.62.3
grpcio-tools==1.62.3
h11==0.16.0
httpcore==1.0.9
httplib2==0.31.2
httptools==0.6.1
httpx==0.27.0
idna==3.11
iso4217parse-fixed==0.1.0
msgpack==1.1.2
multidict==6.7.1
oauthlib==3.3.1
orjson==3.10.14
prometheus_client==0.21.0
propcache==0.4.1
proto-plus==1.27.1
protobuf==4.25.5
pyasn1==0.6.2
pyasn1_modules==0.4.2
pycparser==3.0
pydantic==2.9.2
pydantic-settings==2.5.2
pydantic_core==2.23.4
PyJWT==2.10.1
pyparsing==3.3.2
python-dateutil==2.9.0.post0
python-dotenv==1.2.2
python-logstash==0.4.8
PyYAML==6.0.3
redis==5.1.1
requests==2.32.3
requests-oauthlib==2.0.0
rsa==4.9.1
sentry-sdk==2.25.1
setuptools==82.0.0
six==1.17.0
sniffio==1.3.1
starlette==0.38.6
stripe==11.1.0
tenacity==9.0.0
typing_extensions==4.15.0
uritemplate==4.2.0
urllib3==2.6.3
uvicorn==0.31.0
uvloop==0.20.0
yarl==1.23.0
Request/Response Logs:
Anything else we should know about your project / environment:
Code used for sending events:
client = GoogleAdsClientSync.load_from_string(yaml_str, version="v23")
request = client.get_type('UploadClickConversionsRequest')
request.customer_id = ...
request.conversions.append(...)
request.partial_failure = True
conversion_upload_service = client.get_service('ConversionUploadService', is_async=True)
response = await conversion_upload_service.upload_click_conversions(request, timeout=10) # error occurred here
if response.partial_failure_error.message:
raise SomeError(response.partial_failure_error.message)
Activity
bobhancockg commentedon Mar 3, 2026
Root Cause
In the asynchronous implementation of the Google Ads Python client library, the grpc.aio.Call objects (such as UnaryUnaryCall) do not expose an .exception() method, unlike their synchronous counterparts. The library's internal ExceptionInterceptor and LoggingInterceptor were incorrectly attempting to call this method on asynchronous call objects, leading to the reported AttributeError, especially during failure scenarios like timeouts or invalid requests.
Resolution
These changes should ensure that asynchronous errors are correctly caught, wrapped into GoogleAdsException, and logged without crashing the client.
BenRKarl commentedon Mar 16, 2026
@antonmyronyuk do you have the full stack trace for this?
antonmyronyuk commentedon Mar 17, 2026
@BenRKarl, sure
This method was called inside the FastAPI service, so the traceback is pretty long
BenRKarl commentedon Mar 18, 2026
Thanks @antonmyronyuk - question, do you get a similar error for other types of failed requests? For example, if you intentionally set an invalid customer ID, or specify a bad endpoint in your configuration.
I ask because I'm unable to reproduce this error, and I'm wondering if there's something special about the timeout errors you received (which are hard to reproduce) or the environment where this is happening.
antonmyronyuk commentedon Mar 19, 2026
@BenRKarl , the only way I've reproduced this issue:
developer_token,use_proto_plus(true),client_id,client_secretandrefresh_tokenkeys)And in the main FastAPI service an
AttributeErrorwas raised:google.auth.exceptions.RefreshErrorerror is raises, not the neededAttributeErrorbobhancockg commentedon Mar 19, 2026
BenRKarl commentedon Mar 20, 2026
Just FYI I believe this PR (#1061) addresses this issue, however there are some things in the PR that still need to be addressed, namely failing unit tests. I would also like to reproduce the error myself, which I haven't been able to do, so that I can be sure that we're making the right fix.
fix: await response.code() and use sys.exc_info() in async interceptor