plaid/plaid-python

plaid.exceptions.ApiAttributeError: AccountBalance has no attribute 'last_updated_datetime'

whitneylarow opened this issue · 5 comments

SDK version 8.0.0b9

When the Plaid Python SDK was parsing the response to the /auth/get endpoint for one of our items in production, it threw an exception:

ApiAttributeError(\nplaid.exceptions.ApiAttributeError: AccountBalance has no attribute 'last_updated_datetime' at ['received_data']['accounts'][0]['balances']['last_updated_datetime']

This was thrown while the SDK was parsing the response from Plaid so either Plaid returned an API response that's inconsistent with its API doc contract OR the Plaid Python SDK (version 8.0.0b9) has a bug in how it's parsing the Plaid API response. We already verified that this is not an issue with our own code, it's an issue on Plaid's end.

Plaid support ticket with details on item ID: https://dashboard.plaid.com/support/case/298362

Full stacktrace:

File \"/var/task/src/clients/plaid.py\", line 185, in get_account
    response = get_plaid_client().auth_get(
File \"/var/task/plaid/api_client.py\", line 769, in __call__
    return self.callable(self, *args, **kwargs)
File \"/var/task/plaid/api/plaid_api.py\", line 1573, in __auth_get
    return self.call_with_http_info(**kwargs)
File \"/var/task/plaid/api_client.py\", line 831, in call_with_http_info
    return self.api_client.call_api(
File \"/var/task/plaid/api_client.py\", line 406, in call_api
    return self.__call_api(resource_path, method,
File \"/var/task/plaid/api_client.py\", line 221, in __call_api
    return_data = self.deserialize(
File \"/var/task/plaid/api_client.py\", line 322, in deserialize
    deserialized_data = validate_and_convert_types(
File \"/var/task/plaid/model_utils.py\", line 1392, in validate_and_convert_types
    converted_instance = attempt_convert_item(
File \"/var/task/plaid/model_utils.py\", line 1279, in attempt_convert_item
    return deserialize_model(input_value, valid_class,
File \"/var/task/plaid/model_utils.py\", line 1199, in deserialize_model
    return model_class(**kw_args)
File \"/var/task/plaid/model_utils.py\", line 1564, in wrapped_init
    return fn(self, *args, **kwargs)
File \"/var/task/plaid/model/auth_get_response.py\", line 177, in __init__
    self.accounts = accounts
File \"/var/task/plaid/model_utils.py\", line 165, in __setattr__
    self[attr] = value
File \"/var/task/plaid/model_utils.py\", line 350, in __setitem__
    self.set_attribute(name, value)
File \"/var/task/plaid/model_utils.py\", line 137, in set_attribute
    value = validate_and_convert_types(
File \"/var/task/plaid/model_utils.py\", line 1442, in validate_and_convert_types
    input_value[index] = validate_and_convert_types(
File \"/var/task/plaid/model_utils.py\", line 1392, in validate_and_convert_types
    converted_instance = attempt_convert_item(
File \"/var/task/plaid/model_utils.py\", line 1279, in attempt_convert_item
    return deserialize_model(input_value, valid_class,
File \"/var/task/plaid/model_utils.py\", line 1199, in deserialize_model
    return model_class(**kw_args)
File \"/var/task/plaid/model_utils.py\", line 1564, in wrapped_init
    return fn(self, *args, **kwargs)
File \"/var/task/plaid/model/account_base.py\", line 198, in __init__
    self.balances = balances
File \"/var/task/plaid/model_utils.py\", line 165, in __setattr__
    self[attr] = value
File \"/var/task/plaid/model_utils.py\", line 350, in __setitem__
    self.set_attribute(name, value)
File \"/var/task/plaid/model_utils.py\", line 137, in set_attribute
    value = validate_and_convert_types(
File \"/var/task/plaid/model_utils.py\", line 1392, in validate_and_convert_types
    converted_instance = attempt_convert_item(
File \"/var/task/plaid/model_utils.py\", line 1279, in attempt_convert_item
    return deserialize_model(input_value, valid_class,
File \"/var/task/plaid/model_utils.py\", line 1199, in deserialize_model
    return model_class(**kw_args)
File \"/var/task/plaid/model_utils.py\", line 1564, in wrapped_init
    return fn(self, *args, **kwargs)
File \"/var/task/plaid/model/account_balance.py\", line 179, in __init__
    setattr(self, var_name, var_value)
File \"/var/task/plaid/model_utils.py\", line 165, in __setattr__
    self[attr] = value
File \"/var/task/plaid/model_utils.py\", line 350, in __setitem__
    self.set_attribute(name, value)
File \"/var/task/plaid/model_utils.py\", line 114, in set_attribute
    raise ApiAttributeError(
plaid.exceptions.ApiAttributeError: AccountBalance has no attribute 'last_updated_datetime' at ['received_data']['accounts'][0]['balances']['last_updated_datetime']

@stephenjayakar can you take a look? this looks like an issue with the beta branch. I'm not sure why this would be happening based on the spec, as 'last_updated_datetime' isn't a required field.

taking a look!

hey @whitneylarow! so I am pretty sure was fixed on Mar 10, which is after the release of v9. Could you try updating -> version 10 or 11 and see if the issue fixes?

yeah looks like this field was added 3 days ago
https://github.com/plaid/plaid-openapi/blame/5415996440505ac353a7abdc7c4046cfb98c7528/2020-09-14.yml#L6281-L6287

additive changes shouldn't break python anymore. i think updating should indeed fix things

Updated and it seems to have fixed this. Thanks!