My lambda function is failing simply because I'm still writing it and I haven't put any code to catch errors just yet...
However I noticed that on the retries, it's not running the same as the first invocation, it seems to have lost access to some data.
I'm using response = s3_client.head_object(Bucket=bucket, Key=key)
to get access to the metadata as suggested by Accessing Meta Data from AWS S3 with AWS Lambda.
On the first invocation, s3_client.head_object(...)
returns exactly what I need. However when the function fails, and the second invocation runs, I get a new error:
[ERROR] ClientError: An error occurred (404) when calling the HeadObject operation: Not Found
Traceback (most recent call last):
File "/var/task/CreateThumbnail.py", line 25, in handler
response = s3_client.head_object(Bucket=bucket, Key=key)
File "/var/task/botocore/client.py", line 357, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/task/botocore/client.py", line 661, in _make_api_call
raise error_class(parsed_response, operation_name)
Why would the successive invocations lose access to this? I've verified that I'm still getting the same response for event
and therefore bucket
and key
etc.
Bonus: Is there another way to get at the metadata?
EDIT 1: This lambda function is called via an S3 POST Trigger...
EDIT 2: This actually only seems to error out maybe 50% of the time, the more files that are dropped into S3, the more it errors. Almost like there's a caching error?
import boto3
import os
import sys
import uuid
from PIL import Image
import PIL.Image
s3_client = boto3.client('s3')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def resize_image(image_path, resized_path):
with Image.open(image_path) as image:
image.thumbnail(tuple(x / 2 for x in image.size))
image.save(resized_path)
def handler(event, context):
logger.info(event)
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
response = s3_client.head_object(Bucket=bucket, Key=key)
logger.info('Response: {}'.format(response))
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)
upload_path = '/tmp/resized-{}'.format(key)
s3_client.download_file(bucket, key, download_path)
resize_image(download_path, upload_path)
s3_client.upload_file(upload_path, '{}resized'.format(bucket), key)