asset_report_get raising TypeError when asset report has warnings
darahayes opened this issue · 4 comments
We recently upgraded from plaid-python 7.x (non OpenAPI version) to plaid-python 9.1.0
Since the upgrade we are seeing a case where client.asset_report_get
throws the following error:
TypeError: __init__() missing 1 required positional argument: 'error'
It looks like if an asset report contains any warnings in the warnings
field, then the client fails to deserialize the response from the API correctly.
I cannot easily provide a way to reproduce but I'll try to provide as much info as possible.
In our application we listen for the assets webhook:
{
"asset_report_id": "xxx--xxx--xxx",
"webhook_code": "PRODUCT_READY",
"webhook_type": "ASSETS"
}
during the handling of that webhook, we use client.asset_report_get
to get the contents of the report and determine if we need to apply filtering.
We saw an example where after receiving a PRODUCT_READY
notification for a report, when we tried to get the report we got the TypeError
mentioned above. I can see the response that came back from the plaid API looked like this:
{
report: {
asset_report_id: 'xxxx',
client_report_id: None,
date_generated: '2022-03-23T11:53:28Z',
days_requested: 19,
items: [...],
user: {}
},
request_id: 'qh5EJhxemMpgEsS',
warnings: [
{
cause: {"display_message":"'This financial institution is not currently responding to requests. We apologize for the inconvenience.'","error_code":"'INSTITUTION_NOT_RESPONDING'","error_message":"'this institution is not currently responding to this request. please try again soon'","error_type":"'INSTITUTION_ERROR'","item_id":"'xxxxxx'"},
warning_code: 'OWNERS_UNAVAILABLE',
warning_type: 'ASSET_REPORT_WARNING'
}
]
}
The stack trace was this:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/code.py", line 90, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api_client.py", line 769, in __call__
return self.callable(self, *args, **kwargs)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api/plaid_api.py", line 1308, in __asset_report_get
return self.call_with_http_info(**kwargs)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api_client.py", line 831, in call_with_http_info
return self.api_client.call_api(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api_client.py", line 406, in call_api
return self.__call_api(resource_path, method,
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api_client.py", line 221, in __call_api
return_data = self.deserialize(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/api_client.py", line 322, in deserialize
deserialized_data = validate_and_convert_types(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1354, in validate_and_convert_types
converted_instance = attempt_convert_item(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1241, in attempt_convert_item
return deserialize_model(input_value, valid_class,
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1161, in deserialize_model
return model_class(**kw_args)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1526, in wrapped_init
return fn(self, *args, **kwargs)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model/asset_report_get_response.py", line 180, in __init__
self.warnings = warnings
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 165, in __setattr__
self[attr] = value
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 350, in __setitem__
self.set_attribute(name, value)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 137, in set_attribute
value = validate_and_convert_types(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1404, in validate_and_convert_types
input_value[index] = validate_and_convert_types(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1354, in validate_and_convert_types
converted_instance = attempt_convert_item(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1241, in attempt_convert_item
return deserialize_model(input_value, valid_class,
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1161, in deserialize_model
return model_class(**kw_args)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1526, in wrapped_init
return fn(self, *args, **kwargs)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model/warning.py", line 183, in __init__
self.cause = cause
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 165, in __setattr__
self[attr] = value
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 350, in __setitem__
self.set_attribute(name, value)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 137, in set_attribute
value = validate_and_convert_types(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1354, in validate_and_convert_types
converted_instance = attempt_convert_item(
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1241, in attempt_convert_item
return deserialize_model(input_value, valid_class,
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1161, in deserialize_model
return model_class(**kw_args)
File "/<redacted>/venv/lib/python3.9/site-packages/plaid/model_utils.py", line 1526, in wrapped_init
return fn(self, *args, **kwargs)
TypeError: __init__() missing 1 required positional argument: 'error'
I was able to capture more detail in Sentry. I can see the failure comes from trying to deserialise the cause
part of the warning.
The call to deserialize_model
that failed had the following args
check_type=True
configuration=<plaid.configuration.Configuration object at 0x7f5733d00790>
kw_args={_check_type: True, _configuration: <plaid.configuration.Configuration object at 0x7f5733d00790>, _path_to_item: ['received_data', 'warnings', 0, 'cause'], _spec_property_naming: True, display_message: 'This financial institution is not currently responding to requests. We apologize for the inconvenience.', error_code: 'INSTITUTION_NOT_RESPONDING', error_message: 'this institution is not currently responding to this request. please try again soon', error_type: 'INSTITUTION_ERROR', item_id: 'v66OZpaA48TRXb1vveBrT450YdENeBUmPRMAO'}
model_class=<class 'plaid.model.cause.Cause'>
model_data={display_message: 'This financial institution is not currently responding to requests. We apologize for the inconvenience.', error_code: 'INSTITUTION_NOT_RESPONDING', error_message: 'this institution is not currently responding to this request. please try again soon', error_type: 'INSTITUTION_ERROR', item_id: 'v66OZpaA48TRXb1vveBrT450YdENeBUmPRMAO'}
path_to_item=['received_data', 'warnings', 0, 'cause']
spec_property_naming=True
Thank you for the super detailed error report, it was very helpful! It looks like the root cause here is probably that our API specification used to generate this library misrepresents the schema of the cause
object -- it specifies it as an item_id
and a nested error
object when your copy and paste of the response data shows that the error
object is actually "flattened" in the response, rather than nested. I'm working on a fix now. Do you guys need a hotfix urgently, or is it ok if we wait for the next regularly scheduled release in ~3 weeks?
I don't want to be too pushy, if we could get a fix that would be ideal, but we could probably wait too. This is a bit off topic to the original issue but the reason we decided to upgrade to the OpenAPI based client is because we were migrating to the Account Select V2 feature which according to the docs - "by March 2022, we will automatically migrate all of your customizations to Account Select v2"
We made all the preparations and enabled it for all of our plaid link customizations in production but we had missed the one recommendation which was to upgrade our python client to at least 8.3.0
(we were on 7.x).
We noticed after enabling account select v2 with the old python client, that in the plaid link flow, users who were redirected back to our application after authenticating with an Oauth institution would be presented with an account selection screen within plaid link after after they had already been presented with an account selection screen on the bank side. We reached out to plaid support and they confirmed that a user who goes through the Oauth flow shouldn't see a second account selection step in plaid link. Their recommendation was to update our plaid python client.
To be honest I don't really understand this recommendation given that the flow is entirely frontend and even though we're on an old python client, we're targeting the latest Plaid API. Unless there is something different about how the newer clients call out to create the plaid link token or the API is doing something differently based on the client version in the request headers.
Again - this is off topic but if you know of any workarounds to get the desired plaid link frontend experience using the outdated client, then we'd be happy to try that out while you get a release out on your regular schedule!
The only reason we recommend upgrading the client library is to enable use of the update.account_selection_enabled
parameter when initializing Link for Update Mode, in order to use Update Mode to pick up new accounts detected by the NEW_ACCOUNTS_AVAILABLE
webhook. This parameter is not supported in older client libraries. If you aren't using this, you can continue to use older client libraries.
While it is true that we can sometimes skip the Plaid Link account selection pane after OAuth account selection, the business logic around this is quite complicated and we do not always skip the pane -- it depends on things like whether you are using multi-select or single-select, whether you use account filtering, and how the specific institution that's being connected to implements their OAuth account selection options. The fact that the pane isn't being skipped is likely expected and shouldn't have anything to do with the client library.
This issue is now fixed. Closing.