Reputation: 460
I have developed an application in Next.js. For the backend I have used the api endpoints configured in Nextjs which rest inside pages/api
. The api end points quite often return 502(Gateway timeout error) or 504(There is a problem with our deployment).
With some research I found out that it was happening because the server was timing out. For Vercel where I have deployed my Nextjs application, the timeout max period for serverless functions is 10s.
The code for one of endpoints(https://bulkbays.com/api/fetchSections) is
import db from "../../config/db";
import Section from "../../Models/Section";
db();
export default async function handler(req, res) {
console.log('Entered the serverless function')
Section.find()
.lean()
.then((sections) => {
console.log('Fetched Sections',sections)
return res.json(sections);
})
.catch((err) => {
console.log('Error in fetching sessions',err)
return res.json({
status: false,
msg: "An unexpected problem occured",
err,
});
});
}
Please someone tell me how could it take more than 10 seconds. Its the simplest of queries one could make. Also the result of this query is just an array of length 9 with objects as items which has strings as its values. It looks sth like this
[
{
"_id":"6092a55478ccc2092c5e41b0",
"images":["http://res.cloudinary.com/bulkbays97/image/upload/v1620223428/eysvsch2hf4ymajizzcn.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223429/qiwa2idfrntiygsfmnx2.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223429/elwhjk7abwcde7ccqcxf.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223428/yuzhe8iehcyj1rmfyr09.jpg"],
"title":"P-Caps",
"createdAt":"2021-05-05T14:01:56.626Z",
"updatedAt":"2021-05-05T14:01:56.626Z","__v":0
},
....
]
This is the log for one of the requests which sent a 502 or 504 response
[GET] /api/fetchSections
14:36:34:38
Status:-1
Duration:10010.32 ms
Init Duration: N/A
Memory Used:60 MB
ID:x7lh8-1620552994128-a44f049a01ae
User Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
2021-05-09T09:36:44.511Z 62c16977-9c5c-42f5-961f-a63083638a9c Task timed out after 10.01 seconds
What should I do? Should I use something like Heroku(not serverless) for this or what?
I made this website for a client and now I do not know what is the problem that's causing this.
Upvotes: 29
Views: 50111
Reputation: 3087
When using Vercel with a Hobby plan, your serverless API routes can only be processed for 5 seconds. This means that after 5 seconds, the route responds with a 504 GATEWAY TIMEOUT error.
To resolve this, you would need to reduce the amount of time your API route takes to respond, or upgrade your Vercel plan.
Upvotes: 35
Reputation: 912
This error occurs because Vercel's serverless environment requires a specific way of handling HTTP requests. Here's how to fix it:
Instead of exporting the NestJS app instance, you need to export a handler function The handler function should process HTTP requests and responses Use a singleton pattern to maintain the app instance across requests
Upvotes: -1
Reputation: 1
You have to set maxDuration in your vercel.json file. On hobby plan you can set 60s as maximum.
Upvotes: 0
Reputation: 1
If you get this error after deploying your application on Vercel, trying to retrieve the data but it turns out error 504(Default timeout). Do this:
For me I was using #MONGODB, #nextjsAPI, #Vercel for deployment when facing that error. I dont't know if it can work for others
Upvotes: 0
Reputation: 21
Just a update on this answer. We're on Next14 now. The top rated answer regarding the hobby plan/ Vercel is absolutely right. However there is now some adjustments that you can make. If you place the following route segment option at the top of your page route (where the server action is being called), on the hobby plan you can choose upto 60 seconds. it really helps because the default was 10 seconds and i was being timed out beforehand.
export const maxDuration = 60
This is provding you're using the NodeJs runtime. But this can also be explicitly stated too...
export const runtime = 'nodejs'
more info here..
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
Upvotes: 0
Reputation: 1
Latest update : 2024
Update your db connection with the following lines of code
const port = process.env.PORT || 1000;
mongoose.connect(process.env.DB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => {
console.log('Connected to MongoDB');
app.listen(port, () => {
console.log(`Server is running on port ${port} :)`);
});
}).catch((error) => {
console.error('Database connection error:', error);
process.exit(1);
});
Upvotes: 0
Reputation: 186
I was struggling with this issue on a personal project for longer than I care to admit. I have 10+ pages/api routes. I forgot to import and add the await connectDb()
to all routes. My routes are called in succession frequently, in development all were 200, but in production, some were 200, and others were 504ing with Vercel's FUNCTION_INVOCATION_ERROR (or whatever it's called) indicating the timeout happened in Vercel's edge function in service of the API route (apologies if my terminology isn't completely correct but it's something to that affect). Apparently in development if you don't connect every API route to MongoDB on every call it won't error, the connection must be constant or shared in a different manner, but in production the connection needs to be remade for each route. Leaving this here in case this saves anyone else time.
Upvotes: 2
Reputation: 11
If you have env variables that you used for your API you should add them to your vercel project. Here's the source: Vercel Environment Variables
.env
file:
MONGODB_URI: "uri-value-here";
Your vercel:
This fixed my issue.
Upvotes: 1
Reputation: 1
Actually it's async await problem. You also need to await from where you are calling your vercel api endpoint if you don't do this vercel environment skips that api call i think they don't run that in backgroud means you need to await until your api not got executed then do your any other works
My problem solved by this
In your server side program you need to await for axios request to be done
await axios.post(`${process.env.DOMAIN}/api/sendMail`, {
email, emailType: "VERIFY", auth: process.env.JWT_TOKEN, otp
})
if i remove await from it
it will be not send mail and also you need to use promises to make all done before executing other codes in your api
await new Promise((resolve, reject) => {
// send mail
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
console.error(err);
reject(err);
} else {
console.log(info);
resolve(info);
}
});
});
return NextResponse.json({ message: "successfully sent" })
Upvotes: 0
Reputation: 49360
For me, I wasn't sending the response properly.
wrong:
return res.status(200);
correct:
res.status(200).send("");
Upvotes: 0
Reputation: 1
I faced similar issue with typegraphql api and mongodb atlas setup. First if someone is struggling with the configuration of vercel I am pasting my vercel.json
{
"version": 2,
"builds": [
{
"src": "build/server.js",
"use": "@vercel/node",
"config": {
"includeFiles": [
"build/**"
]
}
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/build/server.js"
}
]
}
In my case I had an issue of sequence. All I had to do is to change the order. First await for mongo connection, then await for the server
import { ApolloServer } from '@apollo/server'
import { expressMiddleware } from '@apollo/server/express4'
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'
import express from 'express'
import http from 'http'
import cors from 'cors'
import bodyParser from 'body-parser'
import { getSchema } from './schema'
// import geoip from 'geoip-lite'
import MobileDetect from 'mobile-detect'
import dotenv from 'dotenv'
import { Context } from './types/context'
import { connectToMongo } from './mongo'
import { getUserFromRequest } from './utils/token'
dotenv.config()
const graphQlPath = process.env.GRAPHQL_PATH
//TODO: check i18next-fs-backend
async function startApolloServer() {
// Required logic for integrating with Express
const app = express()
// Our httpServer handles incoming requests to our Express app.
// Below, we tell Apollo Server to "drain" this httpServer,
// enabling our servers to shut down gracefully.
const httpServer = http.createServer(app)
// Same ApolloServer initialization as before, plus the drain plugin
// for our httpServer.
const schema = await getSchema()
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
],
introspection: true,
})
await server.start()
app.use(
graphQlPath,
cors({
origin: '*',
}),
bodyParser.json(),
expressMiddleware(server, {
context: async ({ req }) => {
const ip = (req.headers['x-forwarded-for'] || req.socket.remoteAddress) as string
const user = getUserFromRequest(req)
const context: Context = {
req,
user,
ip,
// location: geoip.lookup(ip),
location: null,
md: new MobileDetect(req.headers['user-agent']),
}
return context
},
}),
)
await connectToMongo()
const port = process.env.PORT || 4000
await new Promise<void>((resolve) => httpServer.listen({ port }, resolve))
console.log(`🚀 Server ready at http://localhost:${port}/`)
}
startApolloServer().catch((e) => console.log('cannot start server', e))
Another thing that I faced as an issue was with geoip-lite so I just commented the usage.
Upvotes: 0
Reputation: 93
I had the same issue I did:
npm run build
in terminal and it is working for me.
Upvotes: -2
Reputation: 471
I had the same issue, it is caused by next-auth(in my case). So the problem was with te versions over 4.15.0
. I set the next-auth
version to 4.15.0
it solved the problem for me. Hope it's save some hours for someone.
Upvotes: 2
Reputation: 1
I just encountered this issue as well and managed to solve it.
I was using getStaticProps & getStaticPaths in my page component which works well in development but as soon as I try to deploy in production, there was the invalid json response body error.
Turns out that the getStaticProps & getStaticPaths functions are not establishing a connection to my MongoDB and hence returning undefined which crashed the app.
Solution:
I fixed it by directly connecting to my MongoDB and executing the DB calls from within the getStaticProps & getStaticPaths functions.
Hope this helps someone.
Upvotes: 0
Reputation: 994
I faced the same issue of
Task timed out after 10.01 seconds
with Next.js API endpoints that connect to MongoDB(atlas). The root cause for me is actually that the network access in MongoDB was set to my own IP address and hence disallowed from my deployed application. For those who are facing the same issues with Next.js functions, please also check that MongoDB is configured correctly to accept connections from IP addresses other than your own IP.
See below for context:
NOTE: Vercel uses dynamic IP addresses so you'll need to add an exception to access from any IP address in your MongoDB Atlas dashboard. To do this simplify navigate to the Network Access tab, hit the Add IP Address button, and then hit the Allow Access From Anywhere button or for the Access List Entry enter 0.0.0/0.
Upvotes: 15
Reputation: 460
What I did as a result of constant research was that I posted the API on Heroku and the frontend on Vercel. I read this suggestion in one stackoverflow post from a guy who said that he worked in Vercel and this was the most suitable solution for this.
I think this is a problem with the serverless architecture itself. I tried deploying Nextjs on netlify and faced a similar situation.
Upvotes: 2
Reputation: 642
Try and isolate the source of the issue first, so you know what steps to take next.
For example, try returning some dummy data without using or connecting to the DB.
export default async function handler(req, res) {
console.log('Entered the serverless function')
return { "dummy": "data"}
}
If you still have timeout issues, you now know it's probably because of your Vercel NextJS setup.
If your NextJS setup is not the problem, then you know the issue is caused by your DB. Either the problem is in the query itself, or in the connection.
I'm not sure what DB you're using (I assume it's MongoDB from the syntax).
Most likely possible solutions:
db()
does or what it is. I assume it handles connection to the MongoDB instance. Either way, make sure to check if the db()
function is asynchronous or not. It's a common mistake; If the function is async and you don't call it properly, then it's possible that the timeout is caused by this asynchronous issue.If these don't work, try the below:
Upvotes: 7