amazonka
amazonka copied to clipboard
S3 error matchers don't match anything
Rather unfortunate. It seems the S3 service definition has completely nonsensical metadata for the errors.
For example attempting to catch _NoSuchBucket
will never succeed given the following S3 response:
ServiceError'
{_serviceAbbrev = Abbrev "S3"
, _serviceStatus = Status {statusCode = 404, statusMessage = "Not Found"}
, _serviceHeaders = [...]
, _serviceCode = ErrorCode "Not Found"
, _serviceMessage = Nothing
, _serviceRequestId = Just (RequestId "...")
}
And the current definition for _NoSuchBucket
:
_NoSuchBucket = _ServiceError . hasCode "NoSuchBucket"
Given there is no other obvious metadata available, other than to match known error codes such as "Not Found"
above, I'm still pondering how best to fix this.
Just got hit by this when trying to check if a key (Object) exists in an S3 bucket. For anyone else who's relatively new to this or is wondering how to handle these errors, you can create a simple lens like this :
_NotFound :: AsError a => Getting (First ServiceError) a ServiceError
_NotFound = _MatchServiceError s3 "Not Found"
You'll have to import AsError
, Getting
, Service Error
, s3
and _MatchServiceError
from the corresponding amazonka-core
, amazonka-*
packages.
The handling + request
code would look something like : (handling
is from Control.Exception.Lens
from the lens
package, I think amazonka
also has a similar function in the amazonka-lens
package)
handling _NotFound {- Lambda to handle your exception here -} $ do
response <- send $ headObject (BucketName bucketName) (ObjectKey key)
In my case, I'm making a headObject
call in order to just get the metadata of an object (my goal is to check if the object exists)
Given that there's a workaround, I'm punting this until after 2.0.
About five months ago, a botocore update added HTTP status codes to the S3 service definition:
https://github.com/boto/botocore/blob/c5ddcdbe0d53d1a7027ddfa94de40ae7646bec7e/botocore/data/s3/2006-03-01/service-2.json#L7466
I advanced the botocore
pin, regenerated the S3 SDK, and tested it thus:
ghci> Amazonka.runResourceT . trying S3._NoSuchKey . Amazonka.send env $ S3.newGetObject "<redacted>" "nothing"
Left (ServiceError' {abbrev = Abbrev {fromAbbrev = "S3"}, status = Status {statusCode = 404, statusMessage = "Not Found"}, headers = [("x-amz-request-id","<redacted>"),("x-amz-id-2","<redacted>"),("Content-Type","application/xml"),("Transfer-Encoding","chunked"),("Date","Thu, 18 Apr 2024 04:34:43 GMT"),("Server","AmazonS3")], code = ErrorCode "NoSuchKey", message = Just (ErrorMessage {fromErrorMessage = "The specified key does not exist."}), requestId = Just (RequestId {fromRequestId = "<redacted>"})})
Note that it correctly returns a Left
instead of throwing an exception.
However, we cannot advance botocore
right now because the current generator emits non-compiling SDKs for some services on newer botocore pins. See this comment for the full details.
I'm going to tag this generator
and come back to it after the generator gets fixed (which should happen after 2.1).
Actually, I can also get a Left
using trying S3._NoSuchKey
on the released amazonka-2.0
.
Here is what S3 is sending these days (from the trace-level log):
[ServiceError] {
service = S3
status = 404 Not Found
code = NoSuchKey
message = Just The specified key does not exist.
request-id = Just <redacted>
}
So I guess this has become fine at some point?