If I try to get an object from my S3 bucket that doesn't exist, the Amazon PHP SDK 2 gives me a pretty ugly error. Handy for me but means nothing to the end user...
E.g:
$s3 = $aws->get('s3');
$result = $s3->getObject(array(
'Bucket' => 'my bucket',
'Key' => 'path/to/file'
));
The error:
Fatal error: Uncaught Aws\S3\Exception\NoSuchKeyException: AWS Error Code: NoSuchKey, Status Code: 404, AWS Request ID: xxxxxxxxxxxxx, AWS Error Type: client, AWS Error Message: The specified key does not exist. thrown in AWS/vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php on line 89
Is there a way that I can determine if there is an error and print a message that makes sense rather than the above?
You can also use this method:
$response = $s3->doesObjectExist( $bucket, $key );
It will return a boolean true response if the object exists.
AWS Docs for doesObjectExist
It suddenly occurred to me to try this:
All errors that occur in calls to methods of the AWS SDK are indicated by throwing exceptions. You can catch those exceptions if you want to handle the errors.
In the simplest case, you might just want to catch
Exception
:If you only want to handle certain expected exceptions, though, while letting others bubble up and crash your application, then things get a little more subtle.
Firstly, each of the few dozen namespaces within the AWS namespace contains an
Exception
namespace in which it defines exception classes. One of these classes in each namespace is what Amazon calls the default service exception class for the namespace, from which all other exceptions inherit.For example, S3 has the
Aws\S3\Exception
namespace and theS3Exception
class. EC2 has theAws\Ec2\Exception
namespace and theEc2Exception
class.Note that catching one of these exceptions instead of the base
Exception
class immediately stops us catching certain errors! The service-specific exceptions are thrown as a result of error responses from the server; connection failure exceptions do not inherit from them. For example, if you try running the following code without an internet connection...... then the exception will not be caught (since it will be a
Guzzle\Http\Exception\CurlException
, not an S3Exception) and the program will crash. For this reason, if you're catching these exceptions just to provide generic failure messages to the user, you should probably catchException
.Let's return to the question of how to handle a specific error. For most of the namespaces, the answer is that there will be an exception class defined for that error, and you should catch that. For example, let's say we're again using the S3
getObject
method and want to do something when the bucket we ask for doesn't exist. Looking in the S3 Exception namespace docs, we see that there is aNoSuchBucketException
we can catch:(In practice, it may well be easier to figure out which exceptions can be thrown by what operations through trial and error than through carefully reading the docs.)
Finally, it is worth mentioning the EC2 API. Unlike all the other services, the EC2 namespace includes only a single exception class, the
Ec2Exception
. If you want to catch and handle a specific error, you need to inspect the exception object to figure out what kind of error you're dealing with. You can do this by checking the value returned by thegetExceptionCode()
method of the exception.For example, a (modified) snippet from a script I recently wrote that grants specified IPs access to our MySQL server:
Note that the possible exception codes - like
InvalidPermission.Duplicate
in this case - are not listed in the AWS PHP SDK documentation, but you can find them by trial and error or from the documentation for the EC2 API itself, in which each API action's page contains an 'Errors' section listing the error codes it can return.