Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch `botocore.errorfactory.UserNotFoundException`?

I am using AWS Cognito to make OAuth server. I am now creating the exception handler in case use does not exist, but requests intended to get one

ipdb> pk
'David'
ipdb> res = self.cognito_client.admin_get_user(
            UserPoolId=settings.AWS_USER_POOL_ID,
            Username=pk
        )
*** botocore.errorfactory.UserNotFoundException: An error occurred (UserNotFoundException) when calling the AdminGetUser operation: User does not exist.
Traceback (most recent call last):
  File "/Users/sarit/.pyenv/versions/futuready-titan/lib/python3.8/site-packages/botocore/client.py", line 316, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/Users/sarit/.pyenv/versions/futuready-titan/lib/python3.8/site-packages/botocore/client.py", line 626, in _make_api_call
    raise error_class(parsed_response, operation_name)
boto3==1.12.15            # via -r el.in
botocore==1.15.15         # via boto3, s3transfer
django==3.0.3
python3.8.1

I had checked with botocore source code UserNotFoundException

Question:
How can I specifically catch this exception?

like image 419
joe Avatar asked Mar 16 '20 09:03

joe


People also ask

What is botocore exceptions?

Catching botocore exceptions Botocore exceptions are statically defined in the botocore package. Any Boto3 clients you create will use these same statically defined exception classes. The most common botocore exception you'll encounter is ClientError .

How do you create an exception in Python?

In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause. We can thus choose what operations to perform once we have caught the exception.


3 Answers

When an exception is created by botocore.error_factory then it is not possible to directly import it. Instead of direct import, you should use generated classes for exceptions.

A list of possible exceptions is provided for each operation in the documentation. For example, for CognitoIdentityProvider.Client.admin_get_user, possible exceptions are:

CognitoIdentityProvider.Client.exceptions.ResourceNotFoundException
CognitoIdentityProvider.Client.exceptions.InvalidParameterException
CognitoIdentityProvider.Client.exceptions.TooManyRequestsException
CognitoIdentityProvider.Client.exceptions.NotAuthorizedException
CognitoIdentityProvider.Client.exceptions.UserNotFoundException
CognitoIdentityProvider.Client.exceptions.InternalErrorException

There is an example of how to get the list of examples for a client and how to handle it (of course list of exceptions is depend from operation):

import boto3

eks = boto3.client('eks')
print(dir(eks.exceptions))
# ['BadRequestException', 
# 'ClientError', 
# 'ClientException',
# 'InvalidParameterException',
# 'InvalidRequestException',
# 'NotFoundException',
# 'ResourceInUseException',
# 'ResourceLimitExceededException',
# 'ResourceNotFoundException',
# 'ServerException',
# 'ServiceUnavailableException',
# 'UnsupportedAvailabilityZoneException', ...]
try:
    response = eks.list_nodegroups(clusterName='my-cluster')
except eks.exceptions.ResourceNotFoundException as e:
    # do something with e
    print("handled: " + str(e))

cognito_idp = boto3.client('cognito-idp')
print(dir(cognito_idp.exceptions))
# [ 'ClientError', 
# 'ConcurrentModificationException',
# 'DeveloperUserAlreadyRegisteredException',
# 'ExternalServiceException',
# 'InternalErrorException',
# 'InvalidIdentityPoolConfigurationException',
# 'InvalidParameterException',
# 'LimitExceededException',
# 'NotAuthorizedException',
# 'ResourceConflictException',
# 'ResourceNotFoundException',
# 'TooManyRequestsException', ... ]
try:
    response = cognito_idp.admin_get_user(
        UserPoolId='pool_id',
        Username='username'
    )
except cognito_idp.exceptions.UserNotFoundException as e:
    # do something with e
    print("handled: " + str(e))

Additionally, you may catch the less typed botocore.exceptions.ClientError instead of specific ones:

import boto3
import botocore.exceptions

try:
    response = cognito_idp.admin_get_user(
        UserPoolId='pool_id',
        Username='username'
    )
except botocore.exceptions.ClientError as e:
    # do something with e
    print("handled: " + str(e))
like image 72
Maxim Suslov Avatar answered Oct 24 '22 09:10

Maxim Suslov


This is certainly not ideal, but I am able to catch it with:

from botocore.exceptions import ClientError

try:
    func_that_interacts_with_cognito()
except ClientError:
    # This happens when the user is not found.
    print("It happened again ...")
like image 26
IntrepidDude Avatar answered Oct 24 '22 08:10

IntrepidDude


There's two ways, you can catch the exception directly if it is exposed on the client, or import from botocore.exceptions and use that instead.

Option 1:

try: 
    res = self.cognito_client.admin_get_user(
              UserPoolId=settings.AWS_USER_POOL_ID,
              Username=pk
          )
except self.cognito_client.exceptions.UserNotFoundException as e:
    print(e)

Option 2:

from botocore.exceptions import UserNotFoundException

try: 
    res = self.cognito_client.admin_get_user(
              UserPoolId=settings.AWS_USER_POOL_ID,
              Username=pk
          )
except UserNotFoundException as e:
    print(e)

See botos error handling documentation for more detailed information.

like image 5
Carl Avatar answered Oct 24 '22 08:10

Carl