0

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)
dangel
  • 7,238
  • 7
  • 48
  • 74

1 Answers1

0

Turns out I was uploading some files with a bracket [ in the name...

According to https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html under "Characters to Avoid" this is not advised.

Thanks to What are valid S3 key names that can be accessed via the S3 rest API? for pointing me to this resource.

dangel
  • 7,238
  • 7
  • 48
  • 74