My website built with NextJS (and hosted with Vercel) is using Mongoose in my NodeJS API to connect to my MongoDB database.
I get this weird error for only about 1% of the users:
MongooseError: Cannot call `hotels.aggregate()` before initial connection is complete if `bufferCommands = false`. Make sure you `await mongoose.connect()` if you have `bufferCommands = false`.
at NativeCollection.<computed> [as aggregate] (/var/task/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:193:15)
at /var/task/node_modules/mongoose/lib/aggregate.js:998:18
at /var/task/node_modules/kareem/index.js:23:7
at processTicksAndRejections (internal/process/task_queues.js:77:11)
(hotels is the collection that is being displayed, and I'm calling the .aggregate() function on it in my API)
I can't reliably reproduce the error, but have had it happen to me too.
I'm following NextJS recommended way to connect to MonogoDB from their example:
import mongoose from 'mongoose'
const MONGODB_URI = process.env.MONGODB_URI
if (!MONGODB_URI) {
throw new Error(
'Please define the MONGODB_URI environment variable inside .env.local'
)
}
/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
let cached = global.mongoose
if (!cached) {
cached = global.mongoose = { conn: null, promise: null }
}
async function dbConnect() {
if (cached.conn) {
return cached.conn
}
if (!cached.promise) {
const opts = {
bufferCommands: false,
}
cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
return mongoose
})
}
cached.conn = await cached.promise
return cached.conn
}
export default dbConnect
Contrary to the error message, I am awaiting the mongoose.connect(). My API starts like this:
import dbConnect from "utils/dbConnect";
import HotelModel from "models/HotelModel";
export default async function handler(req, res) {
await dbConnect();
try {
const pipeline = {}; // this is a big aggregation pipeline
const hotels = await HotelModel.aggregate(pipeline);
return res.status(200).json(hotels);
} catch{
...
}
}
Does anyone have ideas to why this might happen?
CodePudding user response:
Add this to connection options:
bufferMaxEntries:0
bufferMaxEntries - The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set bufferCommands to false on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.
CodePudding user response:
Remove
const opts = {
bufferCommands: false,
}
or set bufferCommands: true explicitly.
Vercel is running on AWS Lambda, and sometimes it causes problems with cached connections. One of the Vercel contributors complained about the corresponding PR in mongoose https://github.com/Automattic/mongoose/issues/9239#issuecomment-659000910
They recommended to avoid bufferCommands: false in the thread and removed it from the official mongoose recommendations a year later: docs/lambda.md
