Solution Provided in the End
This is my app.js code
const express = require("express");
const mongoose = require("mongoose");
const app = express();
app.set("view engine", "ejs");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/todolistDB");
const itemsSchema = {
name: String,
};
const Item = mongoose.model("Item", itemsSchema);
const item1 = new Item({
name: "Drink Water",
});
const item2 = new Item({
name: "Go for a run",
});
const defaultItems = [item1, item2];
// Item.insertMany(defaultItems)
const listSchema = {
name: String,
items: [itemsSchema],
};
const List = mongoose.model("List", listSchema);
app.get("/", async function (req, res) {
let allItems;
try {
allItems = await Item.find();
} catch (err) {
console.log(err);
}
console.log(allItems);
return res.render("i");
});
app.post("/", async function (req, res) {
let item = new Item({
name: req.body.newItem.trim(),
});
let listName = req.body.list;
if(listName === "today"){
item.save();
return res.redirect("/");
}
let foundList = await List.findOne({name: listName}).exec();
foundList.items.push(item);
foundList.save();
return res.redirect("/"+listName);
});
app.post("/delete", async function (req, res) {
let id = req.body.checkbox;
let listName = req.body.listName.toLowerCase();
if(listName === "today"){
try {
const item = await Item.findByIdAndDelete(id);
} catch (err) {
console.log(err);
}
return res.redirect("/");
}
let foundList = await List.findOne({name: listName}).exec();
foundList.items.pull({_id: id});
foundList.save();
return res.redirect("/"+listName);
});
app.get("/:listName", async function (req, res) {
let { listName } = req.params;
if(listName.toLowerCase() == "delete"){
return res.redirect("/");
}
let foundList = await List.findOne({name: listName.toLowerCase()}).exec();
if(!foundList){
const list = new List({
name: listName,
items: [],
});
list.save();
foundList = list;
}
return res.render("list", {
listTitle: listName,
items: foundList.items,
});
});
app.listen(3000, function () {
console.log("Server started on port 3000");
});
This is my package.json code
{
...
"dependencies": {
"ejs": "^3.1.9",
"express": "^4.18.2",
"mongoose": "^7.3.1"
},
"devDependencies": {
"nodemon": "^2.0.22"
}
}
Node and npm version:
node -v
v18.16.1
npm -v
8.13.2
There was absolutely no problem connection to localhost mongodb, until I tested one of my apps on Atlas cluster, and updated node.js to v18.16.1. Now the connection gets established and the code works perfectly fine when using Atlas cluster, but it is not working for localhost anymore.
I'm using nodemon so I can also continuously track errors. Initially I'm getting the following error when starting *localhost:3000: on my browser:
MongooseError: Operation `items.find()` buffering timed out after 10000ms
at Timeout.<anonymous> (D:\Projects\to-do-list\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:23)
at listOnTimeout (node:internal/timers:569:17)
at process.processTimers (node:internal/timers:512:7)
undefined
D:\Projects\to-do-list\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185
const err = new MongooseError(message);
^
MongooseError: Operation `lists.findOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (D:\Projects\to-do-list\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:23)
at listOnTimeout (node:internal/timers:569:17)
at process.processTimers (node:internal/timers:512:7)
Node.js v18.16.1
When I modified the code to write something to the database instead of reading with Item.find()
in app.get("/")
, I'm getting the following error:
D:\Projects\to-do-list\node_modules\mongoose\lib\model.js:3237
for (let i = 0; i < error.writeErrors.length; ++i) {
^
TypeError: Cannot read properties of undefined (reading 'length')
at D:\Projects\to-do-list\node_modules\mongoose\lib\model.js:3237:47
I tried console logging the mongodb connection status using console.log(mongoose.connection.readyState)
and its giving the value 2
which meaning Connecting.
After waiting for a while without exiting the nodemon terminal, I'm getting the following error:
D:\Projects\to-do-list\node_modules\mongoose\lib\connection.js:792
err = new ServerSelectionError();
^
MongooseServerSelectionError: connect ECONNREFUSED ::1:27017
at _handleConnectionErrors (D:\Projects\to-do-list\node_modules\mongoose\lib\connection.js:792:11)
at NativeConnection.openUri (D:\Projects\to-do-list\node_modules\mongoose\lib\connection.js:767:11) {
reason: TopologyDescription {
type: 'Unknown',
servers: Map(1) {
'localhost:27017' => ServerDescription {
address: 'localhost:27017',
type: 'Unknown',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 0,
roundTripTime: -1,
lastUpdateTime: 20551391,
lastWriteDate: 0,
error: MongoNetworkError: connect ECONNREFUSED ::1:27017
at connectionFailureError (D:\Projects\to-do-list\node_modules\mongodb\lib\cmap\connect.js:370:20)
at Socket.<anonymous> (D:\Projects\to-do-list\node_modules\mongodb\lib\cmap\connect.js:293:22)
at Object.onceWrapper (node:events:628:26)
at Socket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
cause: Error: connect ECONNREFUSED ::1:27017
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16) {
errno: -4078,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '::1',
port: 27017
},
[Symbol(errorLabels)]: Set(1) { 'ResetPool' }
},
topologyVersion: null,
setName: null,
setVersion: null,
electionId: null,
logicalSessionTimeoutMinutes: null,
primary: null,
me: null,
'$clusterTime': null
}
},
stale: false,
compatible: true,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
setName: null,
maxElectionId: null,
maxSetVersion: null,
commonWireVersion: 0,
logicalSessionTimeoutMinutes: null
},
code: undefined
}
I have tried starting the mongodb server both from Compass and mongosh.
When I tried checking which app/services are using the port "27017", I found all the PID mentioned point to Compass only:
Even telnet on localhost 27017 was successful
I have tried:
- Deleting the node_modules package and *.json files, and reinstalling all dependencies.
- Uninstalling and reinstalling mongodb.
- Restarting Compass.
- Restarting system.
- Starting server from Compass
- Starting server from mongosh
The main problem here seems to be MongoDB not connecting or refusing to connect: MongooseServerSelectionError: connect ECONNREFUSED ::1:27017
, as timeout and other errors won't even occur if it had been successfully connected.
Please help me fix this the error
Soution
The problem turned out to be localhost using ipv6 address, and MongoDB running on ipv4.
Some solutions that I found are:
- Adding a
family: 4
option asmongoose.connect("mongodb://localhost:27017/todolistDB",{family: 4});
. This tells the localhost to use ipv4. - Running
mongod --ipv6
on terminal. Localhost uses ipv6 so this--ipv6
enables ipv6 access for mongodb. - Replacing
localhost
inmongoose.connect("mongodb://localhost:27017/todolistDB");
with127.0.0.1
admongoose.connect("mongodb://127.0.0.1:27017/todolistDB");
.127.0.0.1
is the localhost ipv4 address.::1
is the localhost ipv6 address - Use node v16