Returning custom http status codes on AWS Lambda error - aws-lambda

I'm working with an AWS Lambda with serverless framework and I want to return a custom http status code when an error occurs but I'm always getting a 502 status code when I call my endpoint with axios.
module.exports.handler = async (event, context, callback) => {
try {
// some stuff
} catch (err) {
// error here
let myErrorObj = {
errorType : "InternalServerError",
httpStatus : 500,
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
},
body: err
}
callback(JSON.stringify(myErrorObj));
}
}
But the object I'm getting back contains the property status: 502 and data.message: "Internal server error"
Any ideas of what is going on here?

status code 502 indicates the lambda's response to API Gateway is in an incorrect format.
The correct response for an async function (if not integration method stated in serverless YAML file, it would use Lambda Proxy Integration):
export const dummyFunction = async (event, context, callback) =>
{
// ... logic
return {
statusCode: 500,
body: JSON.stringify({...data}),
}
};
Callback is only for non-async function only. Please refer to full documentation.

Are you using API Gateway with your Lambda? If so, what you are returning in the callback is incorrect. The object you return must match this format: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
So you can either just callback(err) and let AWS generate a 500 or if you want the added error context something like:
let myErrorObj = {
statusCode : 500,
body: JSON.stringify({
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
}
error: err
}
})
}
callback(null, myErrorObj);
If you want requestId and trace attributes you would need to add them into the body.

Related

SQS send message error using #aws-sdk node js at AWS lambda

I am trying to send message from my AWS Lambda to AWS SQS but it isn't quiet working and throwing me the error.
2022-12-26T14:58:31.651Z 282ada00-ea4a-45b6-afe4-e3a7f16e8c5a INFO MissingParameter: The request must contain the parameter Label.
at throwDefaultError (/var/task/node_modules/#aws-sdk/smithy-client/dist-cjs/default-error-handler.js:8:22)
at deserializeAws_queryAddPermissionCommandError (/var/task/node_modules/#aws-sdk/client-sqs/dist-cjs/protocols/Aws_query.js:292:51)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /var/task/node_modules/#aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
at async /var/task/node_modules/#aws-sdk/middleware-signing/dist-cjs/middleware.js:14:20
at async /var/task/node_modules/#aws-sdk/middleware-retry/dist-cjs/retryMiddleware.js:27:46
at async /var/task/node_modules/#aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:5:22
at async sendToSQS (/var/task/sendToSqs.js:28:20)
at async exports.handler (/var/task/index.js:19:22) {
'$fault': 'client',
'$metadata': {
httpStatusCode: 400,
requestId: 'bf137e9a-24bc-52bd-9416-22b99c6b82f5',
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
Type: 'Sender',
Code: 'MissingParameter',
Detail: ''
}
I am not sure what parameters and in which way I need to include to make it work.
This is my code for sending message, where from my main module I send a simple data value as part of my message to be sent to SQS.
const { SQSClient, AddPermissionCommand } = require("#aws-sdk/client-sqs");
const sendToSQS=async(data)=>{
const client = new SQSClient({ region: "eu-west-1" });
var params = {
DelaySeconds: 0,
MessageAttributes: {
"Author": {
DataType: "String",
StringValue: "event params"
},
},
MessageGroupId:`${data}`,
MessageBody:JSON.stringify(data),
QueueUrl:"https://sqs.eu-west-1.amazonaws.com/000011110000/Salesforce-cqd-orders-delayer-retry"
};
try{
const command = new AddPermissionCommand(params);
let queueRes = await client.send(command);
console.info("[LAMBDA/#sqs] retry mechanism has succeeded. Data sent to SQS successfully")
console.log(queueRes)
const response = {
statusCode: 200,
body: "Data sent from lambda to sqs successfully.",
};
return response
}catch(error){
console.error("[LAMBDA/#s] retry mechanism has failed. Data wasn't sent to SQS")
console.log(error)
const response = {
statusCode: 200,
body: "Lambda to SQS error",
};
return response;
}
}
module.exports={sendToSQS}
Your message has delaySeconds which is not required and MessageGroupId which is only required for FIFO queue.
You can check sendMessage code reference from here AWS Wiki
Also, check this API reference for Send Message

NodeJS: AWS SDK V3: Not receiving any response data from lambda function

I'm trying to use the v3 javascript sdk to invoke a AWS Lambda function, and I'm having problems getting any meaningful response.
My code looks like so...
const { Lambda } = require("#aws-sdk/client-lambda");
const client = new Lambda();
const params = {
FunctionName: "MyLamdaFuncton",
Payload: JSON.stringify({ "action": "do_something" }),
InvocationType: "Event"
};
client.invoke(params)
.then((response) => {
console.log(JSON.stringify(response,null,4));
})
.catch((err) => {
console.error(err);
})
I can confirm from checking the CloudWatch logs that the lambda function works as exepcted. However this is the response I get in my NodeJS code...
{
"$metadata": {
"httpStatusCode": 202,
"requestId": "d6ba189d-9156-4f01-bd51-efe34a66fe34",
"attempts": 1,
"totalRetryDelay": 0
},
"Payload": {}
}
How do I get the actual response and status from the Lambda function?
If I change the payload above to intentionally throw an exception in my Lambda, the response in the console is still exactly the same.
update:
The Lambda function is written in Ruby. The response is returned like so...
{ statusCode: 200, body: JSON.generate(response.success?) }
where "response" is from another service it calls internally.
I've figured out what I was doing wrong. The issue was the "InvocationType". I got it working by changing to...
InvocationType: "RequestResponse"
Then I had to extract the response data like so...
const response_data = JSON.parse(new TextDecoder("utf-8").decode(response.Payload))

AWS lambda api gateway error “Malformed Lambda proxy response”

My AWS ApiGateway invokes this lambda function :
const handler = (event, context) => {
const theResponse = {
"statusCode": 200,
"isBase64Encoded": false,
"headers": {
"Content-Type": "application/json"
},
"body": "hello, world"
};
switch (event.httpMethod) {
case 'GET':
theResponse["body"] = `method ${event.httpMethod} detected`;
break;
default:
theResponse["statusCode"] = 404;
theResponse["body"] = `Unsupported method ${event.httpMethod} detected`;
break;
}
return theResponse;
};
module.exports = {
handler,
};
Any thoughts to why this errors with :
{"message": "Internal server error"}
Received response. Status: 200, Integration latency: 344 ms
Endpoint response body before transformations: null
Execution failed due to configuration error: Malformed Lambda proxy response
Method completed with status: 502
I tried replacing return (theResponse); with return JSON.stringify(theResponse); but this also returns the same error.
However if I replace return theResponse; with return {"statusCode":200, "body":"hello, world"}; then the API executes without errors.
Looks to me like a lamda_proxy integration issue but I can't see why. thanks.
Bearrider!
I guess it is related to the way you are building your response object:
Try stringify only the body attribute:
case 'GET':
theResponse["body"] = JSON.stringify(`method ${event.httpMethod} detected`);
break;
default:
theResponse["statusCode"] = 404;
theResponse["body"] = JSON.stringify(`Unsupported method ${event.httpMethod} detected`);
break;
}

Parse Cloud Function Response Error

I wrote this cloud funtion for demo purpose.
Parse.Cloud.define('hello', function(req, res) {
res.success("hi");
});
But it always returns this error message
{
"code": 141,
"error": "res.success is not a function"
}
What's wrong?
Starting parse server 3.0 there is no response object anymore. Simply return the value and it will work.
Parse.Cloud.define(‘hello’, (req) => {
return ‘ok’;
});
For more informations, see the migration guide: https://github.com/parse-community/parse-server/blob/master/3.0.0.md

custom authorizers in Amazon API Gateway 500 error

I use Serverless-Authentication-boilerplate and want to map custom error response. But it always return 500 error.
authorize.js
// Authorize
function authorize(event, callback) {
let providerConfig = config(event);
try {
let data = utils.readToken(event.authorizationToken, providerConfig.token_secret);
console.log("Decrypted data: " + JSON.stringify(data));
let methodArn = event.methodArn.replace(/(GET|POST|PUT|DELETE)/g, '*').replace(/mgnt.+/g, 'mgnt/*');
console.log(`Change methodArn to: ${methodArn}`);
// TODO: handle expiration time validation
callback(null, utils.generatePolicy(
data.id, // which is $context.authorizer.principalId
'Allow',
methodArn));
} catch (err) {
console.log(err);
callback('401 Unauthenticated');
}
}
s-function.json
responses:{
"401 Unauthenticated.*": {
"statusCode": "401"
},
"default": {
"statusCode": "200",
"responseModels": {
"application/json;charset=UTF-8": "Empty"
},
"responseTemplates": {
"application/json;charset=UTF-8": ""
}
}
}
After ask to Amazon Web Services.
Unfortunately the mapping of the Authorizer is not currently configurable and every returned error from a lambda function will map to a 500 status code in API gateway. Moreover, the mapping is performed on an exact string match of the output, so, in order to return the intended 401 Error to the client, you should execute a call to 'context.fail('Unauthorized');.
Finally, I change
callback('401 Unauthenticated');
to
context.fail('Unauthorized');
and work fine.
Sharing to whom may encounter this.

Resources