alexpareto commented on Jul 22, 2019
An ugly, but workable solution to find out what exceptions are available on each client from the command line:
import boto3
client = boto3.client('sns') # or whatever client you're using
# client.exceptions.__dict__
client.exceptions.__dict__['_code_to_exception'].keys()
should print something like this:
{'_code_to_exception': {'AuthorizationError': <class 'botocore.errorfactory.AuthorizationErrorException'>, 'EndpointDisabled': <class 'botocore.errorfactory.EndpointDisabledException'>, 'InternalError': <class 'botocore.errorfactory.InternalErrorException'>, 'InvalidParameter': <class 'botocore.errorfactory.InvalidParameterException'>, 'ParameterValueInvalid': <class 'botocore.errorfactory.InvalidParameterValueException'>, 'NotFound': <class 'botocore.errorfactory.NotFoundException'>, 'PlatformApplicationDisabled': <class 'botocore.errorfactory.PlatformApplicationDisabledException'>, 'SubscriptionLimitExceeded': <class 'botocore.errorfactory.SubscriptionLimitExceededException'>, 'Throttled': <class 'botocore.errorfactory.ThrottledException'>, 'TopicLimitExceeded': <class 'botocore.errorfactory.TopicLimitExceededException'>}}```
dacut commented on May 7, 2019
There are currently (as of version 1.12.142) three base exceptions and two warnings:
- BotoCoreError
- ClientError
- UndefinedModelAttributeError
- ImminentRemovalWarning
- UnsupportedTLSVersionWarning
The ClientError
exception appears to be raised when a remote call is made but the service returns an error. The BotoCoreError
hierarchy appears to reflect issues in creating or handling the call itself. (Why UndefinedModelAttributeError
is not a subclass of BotoCoreError
is a mystery to me.)
Within ClientError
(but not BotoCoreError
), there will be an operation_name
attribute (should be a str) and a response
attribute (should be a dict). The response
attribute should have the following form (example from a malformed ec2.DescribeImages call):
{
"Error": {
"Code": "InvalidParameterValue",
"Message": "The filter 'asdfasdf' is invalid"
},
"ResponseMetadata": {
"RequestId": "aaaabbbb-cccc-dddd-eeee-ffff00001111",
"HTTPStatusCode": 400,
"HTTPHeaders": {
"transfer-encoding": "chunked",
"date": "Fri, 01 Jan 2100 00:00:00 GMT",
"connection": "close",
"server": "AmazonEC2"
},
"RetryAttempts": 0
}
}
Typically, you want to handle specific error codes. Because this is largely only quasi-documented, this is what I typically do for error handling (in this case, handling the InvalidParameterValue
from my ec2.DescribeImages call):
except ClientError as e:
error_code = e.response.get("Error", {}).get("Code")
if error_code == "InvalidParameterValue":
# Do something
pass
else:
raise
Or, if I need to intermingle it with other exception handling code (much rarer) and am feeling lazy about it:
except Exception as e:
error_code = getattr(e, "response", {}).get("Error", {}).get("Code")
...
Here's the full hierarchy of statically defined exceptions/warnings I found programmatically. Note that some exception classes use multiple inheritance.
AliasConflictParameterError < ValidationError < BotoCoreError < Exception
ApiVersionNotFoundError < BotoCoreError < Exception
BaseEndpointResolverError < BotoCoreError < Exception
BotoCoreError < Exception
ChecksumError < BotoCoreError < Exception
ClientError < Exception
ConfigNotFound < BotoCoreError < Exception
ConfigParseError < BotoCoreError < Exception
ConnectTimeoutError < [ConnectionError < BotoCoreError < Exception, ConnectTimeout < [ConnectionError < RequestException < OSError < Exception, Timeout < RequestException < OSError < Exception]]
ConnectionClosedError < HTTPClientError < BotoCoreError < Exception
ConnectionError < BotoCoreError < Exception
CredentialRetrievalError < BotoCoreError < Exception
DataNotFoundError < BotoCoreError < Exception
EndpointConnectionError < ConnectionError < BotoCoreError < Exception
EventStreamError < ClientError < Exception
HTTPClientError < BotoCoreError < Exception
ImminentRemovalWarning < Warning < Exception
IncompleteReadError < BotoCoreError < Exception
InfiniteLoopConfigError < InvalidConfigError < BotoCoreError < Exception
InvalidConfigError < BotoCoreError < Exception
InvalidDNSNameError < BotoCoreError < Exception
InvalidExpressionError < BotoCoreError < Exception
InvalidMaxRetryAttemptsError < InvalidRetryConfigurationError < BotoCoreError < Exception
InvalidRetryConfigurationError < BotoCoreError < Exception
InvalidS3AddressingStyleError < BotoCoreError < Exception
MD5UnavailableError < BotoCoreError < Exception
MetadataRetrievalError < BotoCoreError < Exception
MissingParametersError < BotoCoreError < Exception
MissingServiceIdError < UndefinedModelAttributeError < Exception
NoCredentialsError < BotoCoreError < Exception
NoRegionError < BaseEndpointResolverError < BotoCoreError < Exception
OperationNotPageableError < BotoCoreError < Exception
PaginationError < BotoCoreError < Exception
ParamValidationError < BotoCoreError < Exception
PartialCredentialsError < BotoCoreError < Exception
ProfileNotFound < BotoCoreError < Exception
ProxyConnectionError < [ConnectionError < BotoCoreError < Exception, ProxyError < ConnectionError < RequestException < OSError < Exception]
RangeError < ValidationError < BotoCoreError < Exception
ReadTimeoutError < [HTTPClientError < BotoCoreError < Exception, ReadTimeout < Timeout < RequestException < OSError < Exception, ReadTimeoutError < [TimeoutError < HTTPError < Exception, RequestError < PoolError < HTTPError < Exception]]
RefreshWithMFAUnsupportedError < BotoCoreError < Exception
SSLError < [ConnectionError < BotoCoreError < Exception, SSLError < ConnectionError < RequestException < OSError < Exception]
ServiceNotInRegionError < BotoCoreError < Exception
StubAssertionError < [StubResponseError < BotoCoreError < Exception, AssertionError < Exception]
StubResponseError < BotoCoreError < Exception
UnStubbedResponseError < StubResponseError < BotoCoreError < Exception
UndefinedModelAttributeError < Exception
UnknownClientMethodError < BotoCoreError < Exception
UnknownCredentialError < BotoCoreError < Exception
UnknownEndpointError < [BaseEndpointResolverError < BotoCoreError < Exception, ValueError < Exception]
UnknownKeyError < ValidationError < BotoCoreError < Exception
UnknownParameterError < ValidationError < BotoCoreError < Exception
UnknownServiceError < DataNotFoundError < BotoCoreError < Exception
UnknownServiceStyle < BotoCoreError < Exception
UnknownSignatureVersionError < BotoCoreError < Exception
UnseekableStreamError < BotoCoreError < Exception
UnsupportedSignatureVersionError < BotoCoreError < Exception
UnsupportedTLSVersionWarning < Warning < Exception
ValidationError < BotoCoreError < Exception
WaiterConfigError < BotoCoreError < Exception
WaiterError < BotoCoreError < Exception
Code for how I generated the above (Python 3.7):
def hierarchy(t):
if t is Exception or t is object:
return t.__name__
result = t.__name__ + " < "
if len(t.__bases__) == 1:
result += hierarchy(t.__bases__[0])
else:
result += "[" + ", ".join([hierarchy(base) for base in t.__bases__]) + "]"
return result
# Getting the list of base exceptions/warnings
for key, value in sorted(botocore.exceptions.__dict__.items()):
if isinstance(value, type) and (value.__bases__ == (Exception,) or value.__bases__ == (Warning,)):
print(key)
# Printing the hierarchy
for key, value in sorted(botocore.exceptions.__dict__.items()):
if isinstance(value, type):
print(hierarchy(value))