Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS Lambda Invoke Error: Unable to stringify response body

Created a Lambda function to get analysis from AWS Textract API. Here is the relevant code (Node.js 12)

exports.handler = async (event, context, callback) => {
 ...    
 
   let request = textract.getDocumentAnalysis(params);
   request.send((err, data) => {
       if (err) console.log(err, err.stack);
       else console.log(data);
   });
   
    callback(null, request);
}; 

In CloudWatch logs get this error:

ERROR   Invoke Error    
{
    "errorType": "Error",
    "errorMessage": "Unable to stringify response body",
    "stack": [
        "Error: Unable to stringify response body",
        "    at _trySerializeResponse (/var/runtime/RAPIDClient.js:175:11)",
        "    at RAPIDClient.postInvocationResponse (/var/runtime/RAPIDClient.js:45:22)",
        "    at complete (/var/runtime/CallbackContext.js:33:12)",
        "    at callback (/var/runtime/CallbackContext.js:43:7)",
        "    at /var/runtime/CallbackContext.js:104:16",
        "    at Runtime.exports.handler (/var/task/index.js:92:5)",
        "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
    ]
}

When I modify the callback: callback(null, request.X) ... lambda returns the data object from Textract. I at first thought that I had to drill down into the data object (request.DocumentMetadata) ... but works with any string of characters I put in front of "request." (at least the ones I've tried). Any help with this is appreciated.

like image 530
MC Hammerabi Avatar asked Sep 10 '20 22:09

MC Hammerabi


1 Answers

I was using the above approach due to following AWS SDK API documentation closely. However, I found another approach, which solved all issues (which were many). Maybe someone can explain why.

Here is solution.

let results = await textract.getDocumentAnalysis(params, (err, data) => {
    if(err) console.log(err, err.stack);
    else console.log(data);
}).promise();

callback(null, results);

The answer is relates to the aws-skd (for js). Here is the url: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#promise-property[][1]

For any async request (think all or most all AWS api request will be async), you need a Promise...then. With AWS request you need a "thenable" promise ... so to the end of the request you add: promise()

Straight from AWS docs which can be a bit cryptic I think:

var request = s3.putObject({Bucket: 'bucket', Key: 'key'});
var result = request.promise();
result.then(function(data) { ... }, function(error) { ... });

If I were to write the above like this:

async function(){
  const params = {Bucket: 'bucket', Key: 'key'};
  await s3.putObject(params, (err, data) => {
    if (err) function(err){ ... }; 
    else function(data) { ... };
  }).promise();
};
like image 189
MC Hammerabi Avatar answered Sep 20 '22 14:09

MC Hammerabi