Random Instant Serverless Function Timeouts - node.js

We've been dealing with this issue in our t3 application for over a week now. Here is the error we are getting in the Vercel function logs: 
START RequestId: 3e875969-afce-4409-a7ae-96efc99ff603 Version: $LATEST 2023-01-31T13:43:45.065Z d22a6e7d-0ef6-4aa2-828e-ab70ceb99f02 ERROR Unhandled Promise Rejection  {\"errorType\":\"Runtime.UnhandledPromiseRejection\",\"errorMessage\":\"Error: timeout of 3000ms exceeded\",\"trace\":[\"Runtime.UnhandledPromiseRejection: Error: timeout of 3000ms exceeded\",\" at process.<anonymous> (file:///var/runtime/index.mjs:1194:17)\",\" at process.emit (node:events:525:35)\",\" at process.emit (node:domain:489:12)\",\" at emit (node:internal/process/promises:149:20)\",\" at processPromiseRejections (node:internal/process/promises:283:27)\",\" at process.processTicksAndRejections (node:internal/process/task_queues:96:32)\"]} [ERROR] [1675172625066] LAMBDA_RUNTIME Failed to post handler success response. Http response code: 400. RequestId: 3e875969-afce-4409-a7ae-96efc99ff603 Error: Runtime exited without providing a reason Runtime.ExitError END RequestId: 3e875969-afce-4409-a7ae-96efc99ff603 REPORT RequestId: 3e875969-afce-4409-a7ae-96efc99ff603. Duration: 12.50 ms Billed Duration: 13 ms Memory Size: 1024 MB Max Memory Used: 143 MB"
This only happens to Vercel deployed branches.Notice how it says that it is a 3000ms timeout error but the duration is only 12.50ms.
More details:
All necessary variables (like required user id's for API calls) are provided
The failing API calls succeed most of the time but about 1/5 times they fail.
Includes all our API calls
Example failing API call:
import type { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "../../../server/db/client";
export default async function handler(  
req: NextApiRequest,  res: NextApiResponse) {  
if (req.method === "POST") {    
try {      
const data = JSON.parse(req.body);      
const update = await prisma.user.update({
        where: { id: data.id },
        data: data.data,      
});      
res.json(update);    
} catch (e: any) {      
res.status(500).json({ message: e.message });      
throw new Error("Could't update user:"+ e.message)
    }  
}
}
Note:
The error messages in the catch block are printed nowhere.This is more or less how we call all our serverless functions:
async function updateUserCurrentInstitution({ userId, institutionId }) {  
const response = await fetch(api.updateUser, {
    method: "POST",
    body: JSON.stringify({
      id: userId,
      data: {
        currentInstitution: institutionId,
      },
    }),
  });
  if (!response.ok) {
    throw new Error(response.statusText);
  }
  return response;
}
Any help would be greatly appreciated !

Related

Internal Error to send FCM notification to web application

I'm developing an internal client for triggering firebase cloud messaging push notifications.
With android devices it works without problems. however, when I try to send a notification to a pwa I get the message: FirebaseMessagingError: An internal error has occurred. Please retry the request
This is the code of the function I'm developing:
import admin from '../classes/FirebaseNotification.js';
const priority = 'high';
class FormatNotificationAndroid {
static sendNotification = (data) => {
let registrationTokens = data.devices;
let message = {
notification: {
title: data.notification.title,
body: data.notification.message,
}
};
let options = {
priority: priority,
timeToLive: data.notification.time_to_live
};
console.log(registrationTokens);
console.log(message);
console.log(options);
admin.messaging().sendToDevice(registrationTokens, message, options)
.then(response => {
console.log(response.results);
})
.catch(error => {
console.log(error);
});
}
}
export default FormatNotificationAndroid;
The error trace:
error: FirebaseMessagingError: An internal error has occurred. Please retry the request.
at FirebaseMessagingError.fromServerError (C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\utils\error.js:254:16)
at C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:93:65
at Array.forEach (<anonymous>)
at mapRawResponseToDevicesResponse (C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:89:26)
at C:\projetos\firebase-send-message\node_modules\firebase-admin\lib\messaging\messaging.js:344:24
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
errorInfo: [Object],
codePrefix: 'messaging'

Proper way to handle fetch errors in NodeJS v18?

I switched to NodeJS v18 with the built-in fetch and I'm using it as such:
async function get511AK() {
let res = await fetch(URL, { method: 'GET' })
if (res.ok && (res.headers.get('content-type').includes('json'))) {
let data = await res.json();
jsonresponseAK = data;
} else {
console.log("(" + res.url + ') is not json');
}
}
However, sometimes I'm getting a timeout on the URL, which is going to happen, but it's causing the script to exit. I've tried wrapping this in try/catch and it did not prevent it from exiting.
This never happened in Node v12 under the node-fetch library. What else can I add to control those connection timeouts?
node:internal/deps/undici/undici:11118
Error.captureStackTrace(err, this);
^
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11118:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Timeout.get511AK [as _onTimeout] (/home/wazebot/dot-scripts/script-relay.js:76:12) {
cause: ConnectTimeoutError: Connect Timeout Error
at onConnectTimeout (node:internal/deps/undici/undici:6625:28)
at node:internal/deps/undici/undici:6583:50
at Immediate._onImmediate (node:internal/deps/undici/undici:6614:13)
at process.processImmediate (node:internal/timers:471:21) {
code: 'UND_ERR_CONNECT_TIMEOUT'
}
}
Node.js v18.12.1
Hope it helped!
process.on('uncaughtException', console.log);
// Uncaught Exception thrown - when you throw an error and did not catch anywhere.
process.on('unhandledRejection', console.log);
// Unhandled Rejection at Promise - similar, when you fail to catch a Promise.reject.

Mongoose Unexpected token u in JSON at position 0

I'm creating an AWS Lambda API with Node JS. There's a template for the db connection itself, but when I run a test in Lambda I get an error and I believe the problem is the connection itself.
Here's the error message I get with Lambda test:
START RequestId: 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 Version: $LATEST
2020-05-23T01:46:23.685Z 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 INFO => using new database connection
2020-05-23T01:46:23.689Z 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 ERROR (node:8) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
2020-05-23T01:46:23.726Z 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 ERROR (node:8) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
2020-05-23T01:46:23.828Z 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 ERROR Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"SyntaxError: Unexpected token u in JSON at position 0","reason":{"errorType":"SyntaxError","errorMessage":"Unexpected token u in JSON at position 0","stack":["SyntaxError: Unexpected token u in JSON at position 0"," at JSON.parse ()"," at /var/task/handler.js:17:22"," at processTicksAndRejections (internal/process/task_queues.js:97:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: SyntaxError: Unexpected token u in JSON at position 0"," at process. (/var/runtime/index.js:35:15)"," at process.emit (events.js:310:20)"," at processPromiseRejections (internal/process/promises.js:209:33)"," at processTicksAndRejections (internal/process/task_queues.js:98:32)"]}
END RequestId: 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5
REPORT RequestId: 6b9eef97-9c54-44bc-8ecc-dfbec7e200e5 Duration: 186.61 ms Billed Duration: 200 ms Memory Size: 1024 MB Max Memory Used: 34 MB
Unknown application error occurred
DB.js
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
let isConnected;
module.exports = connectToDatabase = () => {
if (isConnected) {
console.log("=> using existing database connection");
return Promise.resolve();
}
console.log("=> using new database connection");
return mongoose.connect(process.env.DB).then((db) => {
isConnected = db.connections[0].readyState;
});
};
Handler.js
"use strict";
const connectToDatabase = require("./db");
const Lead = require("./leads.model.js");
require("dotenv").config({ path: "./variables.env" });
module.exports.hello = (event, context, callback) => {
console.log("Hello World");
callback(null, "Hello World");
};
module.exports.create = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
connectToDatabase().then(() => {
Lead.create(JSON.parse(event.body))
.then((lead) =>
callback(null, {
statusCode: 200,
body: JSON.stringify(lead),
})
)
.catch((err) =>
callback(null, {
statusCode: err.statusCode || 500,
headers: { "Content-Type": "text/plain" },
body: "Could not create the lead.",
})
);
});
};
variables.env
DB=mongodb+srv://dbUser:password#api-jodqc.mongodb.net/test?retryWrites=true&w=majority
Whenever I see Unexpected token u in JSON at position 0, it usually means JSON.parse is trying to parse undefined. Looking at the code, I only see you executing parse in one spot
Lead.create(JSON.parse(event.body))
I'm guessing when you execute the Lambda, you're passing in an object that looks like a lead directly, so maybe something like below.
{
isALead: true
}
Instead, you need to test with an object that looks like
{
body: "{ \"isALead\": true }"
}

How can I use slack api in aws lambda?

I want to use IncomingWebhook api of #slack/client in aws lambda function. There is something problems in my code. Please notice me how can I use.
This is my code below
const { IncomingWebhook } = require('#slack/client');
const config = require('./config')
exports.handler = (event, context, callback) => {
const webhook = new IncomingWebhook(config.slack.webHookUrl)
webhook.send('Hello there', function(err, res) {
if (err) {
console.log('Error:', err);
context.fail('fail')
} else {
console.log('Message sent: ', res);
context.succeed('succeed')
}
});
}
And This is my errors
{
"errorMessage": "RequestId: 9e1b4362-259d-11e8-b422-91108e46ebe1
Process exited before completing request"
}
Here is console errors
START RequestId: 9e1b4362-259d-11e8-b422-91108e46ebe1 Version: $LATEST
2018-03-12T02:32:33.215Z 9e1b4362-259d-11e8-b422-91108e46ebe1 TypeError: Cannot set property 'text' of undefined
at IncomingWebhook.send (/var/task/node_modules/#slack/client/dist/IncomingWebhook.js:26:26)
at exports.handler (/var/task/index.js:6:11)
END RequestId: 9e1b4362-259d-11e8-b422-91108e46ebe1
REPORT RequestId: 9e1b4362-259d-11e8-b422-91108e46ebe1 Duration: 85.31 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 31 MB
RequestId: 9e1b4362-259d-11e8-b422-91108e46ebe1 Process exited before completing request
This was due to a bug in the Slack client which was reported here: https://github.com/slackapi/node-slack-sdk/issues/479, and subsequently fixed in https://github.com/slackapi/node-slack-sdk/releases/tag/v4.0.1. A simple upgrade to the latest version (v4.3.1 at the time of writing) will fix this.

How to test a function that throws an error asynchronously, using tape?

I am attempting to test this module (receiver.js) for an error thrown:
var request = require('request')
module.exports = function(url){
request({
url: url,
method: 'POST'
}, function(error) {
if(error){
throw error
}
})
}
using this test (test.js):
var test = require('tape')
test('Receiver test', function(t){
var receiver = require('./receiver')
t.throws(function(){
receiver('http://localhost:9999') // dummy url
}, Error, 'Should throw error with invalid URL')
t.end()
})
but tape runs the assertion before the error is thrown, resulting in the following error message:
TAP version 13
# Receiver test
not ok 1 Should throw error with invalid URL
---
operator: throws
expected: |-
[Function: Error]
actual: |-
undefined
at: Test.<anonymous> (/path/to/tape-async-error-test/test.js:5:4)
...
/path/to/receiver.js:9
throw error
^
Error: connect ECONNREFUSED 127.0.0.1:9999
at Object.exports._errnoException (util.js:856:11)
at exports._exceptionWithHostPort (util.js:879:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1062:14)
Is there a way around this?
Generally, using tape, you have to ensure you call assert.end() after the async call has completed. Using promises (would require request-promise and returning the promise):
test('Receiver test', function(t){
// Tells tape to expec a single assertion
t.plan(1);
receiver('http://localhost:9999')
.then(() => {
t.fail('request should not succeed')
})
.catch(err => {
t.ok(err, 'Got expected error');
})
.finally({
t.end();
});
});
Using async/await:
test('Receiver test', async function(t) {
try {
await receiver('http://localhost:9999');
assert.fail('Should not get here');
} catch (err) {
assert.ok(err, 'Got expected error');
}
t.end();
});
The above example is mostly correct but here's a complete working example that compares async to synchronous side by side and also shows how to check for the error message in a manner similar to the tape examples given on tape's README.md.
test('ensure async function can be tested to throw', async function(t) {
// t.throw works synchronously
function normalThrower() {
throw(new Error('an artificial synchronous error'));
};
t.throws(function () { normalThrower() }, /artificial/, 'should be able to test that a normal function throws an artificial error');
// you have to do this for async functions, you can't just insert async into t.throws
async function asyncThrower() {
throw(new Error('an artificial asynchronous error'));
};
try {
await asyncThrower();
t.fail('async thrower did not throw');
} catch (e) {
t.match(e.message,/asynchronous/, 'asynchronous error was thrown');
};
});

Resources