damien
damien

Reputation: 57

Lambda function errorMessage": "Cannot read property 'bucket' of undefined

I have a lambda function that is triggered whenever something is saved in my s3 bucket,

the aim is to read the metadata of a JSON file and insert rows in a dynamoDB table;

for instance a training period starts on the june the 1st and end june 8th and training days are Monday, Wednesday and Friday thus the lambda should insert 4 rows ( 1st, 3rd, 5th, 8th of june)

so far only one row is inserted and then the error occurs and it crashes

The function is triggered well but this error message occurs sometimes.

{
    "errorType": "TypeError",
    "errorMessage": "Cannot read property 'bucket' of undefined",
    "stack": [
        "TypeError: Cannot read property 'bucket' of undefined",
        "    at Runtime.exports.handler (/var/task/index.js:26:44)",
        "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
    ]
}

here is my function

let AWS = require('aws-sdk');
let s3 = new AWS.S3();
let moment = require('moment');
let uuid = require('node-uuid');

let apiSportmTrainingTableName = process.env.API_SPORTM_TRAININGTABLE_NAME
let dynamodb = new AWS.DynamoDB.DocumentClient();


exports.handler =  async (event, context) => {
  //eslint-disable-line
  const Bucket = await event.Records[0].s3.bucket.name;

  const Key = await event.Records[0].s3.object.key;
  const objectHead = await s3.headObject({Bucket, Key}).promise();

  let start = moment(new Date(objectHead.Metadata.trainingstart), "YYYY-MM-DD");
  let end = moment(new Date(objectHead.Metadata.trainingend), "YYYY-MM-DD");
  let days = JSON.parse("[" + objectHead.Metadata.trainingdays + "]");

  try {
    for (let m = moment(start); m.diff(end, 'days') <= 0; m.add(1, 'days')) {

      for (const e of days) {

        if (moment(m).day() === e) {
          let params = {
            TableName: apiSportmTrainingTableName,
            Item: {
              "id": uuid.v1(),
              "trainingDate": moment(m).format('YYYY-MM-DD'),
              "statut": true,
              "athleteCategory": objectHead.Metadata.trainingmembercategory,
              "trainingTime": objectHead.Metadata.trainingtime
            }
          };
          return await dynamodb.put(params).promise();
        }
      }
    }
  } catch (err) {
    console.error('Error', err);
    return;
  }
  context.done(null, 'Successfully processed DynamoDB record'); // SUCCESS with message
};

when the event logs it looks like that

Records: [
    {
      eventVersion: '2.1',
      eventSource: 'aws:s3',
      awsRegion: 'us-east-1',
      eventTime: '2020-05-29T18:34:53.250Z',
      eventName: 'ObjectCreated:Put',
      userIdentity: [Object],
      requestParameters: [Object],
      responseElements: [Object],
      s3: [Object]
    }
  ]
}
```

that a part of logs it fails and then works and then it keeps trying and fail




[logs][1]


  [1]: https://i.sstatic.net/Sj5C7.png

Upvotes: 0

Views: 4751

Answers (1)

Christian
Christian

Reputation: 576

You are using return after inserting data into DynamoDB:

return await dynamodb.put(params).promise();

This returns the result of the DynamoDB operations as the result of the Lambda function, which terminated the execution. This explains why only one record is inserted into DynamoDB. I'd try to remove the return and see if that also removes the error (best guess on my part: the returned value somehow causes another execution with it, but this time missing the S3 event, thus event.Records[0].s3 will be undefined).

Upvotes: 1

Related Questions