MongoDB can be connected with MongoClient but not mongoose - node.js

So when I run my app in deployment, with the backend connecting to MongoDB using MongoClient as follow:
import { MongoClient } from 'mongodb'
const url = process.env.MONGODB_URI
MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true },(err, db)=>{
console.log(url)
db.close()
})
everything works fine. But if I change it into
import mongoose from 'mongoose'
mongoose.Promise = global.Promise
mongoose.connect(url, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true })
mongoose.connection.on('error', () => {
throw new Error(`unable to connect to database: ${url}`)
})
it gives the following error:
webpack://HappyHourWeb/./server/server.js?:29
throw new Error(`unable to connect to database: ${_config_config__WEBPACK_IMPORTED_MODULE_0__["default"].mongoUri}`)
^
Error: unable to connect to database: my_database_url,
at NativeConnection.eval (webpack://HappyHourWeb/./server/server.js?:29:9)
at NativeConnection.emit (node:events:390:28)
at /Users/Hieudo/Documents/Project/HappyHourWeb/node_modules/mongoose/lib/connection.js:807:30
at processTicksAndRejections (node:internal/process/task_queues:78:11)
Any help is greatly appreciated!

According to various sources, including MongoDB Connection String URI reference, Mongoose connection docs (Ctrl+F and search for srv to jump to the right topic) and the most upvoted answer on this question on SO, you should handle standard URIs and DNS URIs differently.
Mongoose accepts a dbName option that is
[...]useful if you are unable to specify a default database in the connection string like with some mongodb+srv syntax connections.
The fact that the native MongoDB driver handles it automatically doesn't necessarily means that Mongoose will. Try separating the DB name from the URI and pass it as the second argument when connecting with Mongoose.
Also, that part of your code :
mongoose.connection.on('error', () => {
throw new Error(`unable to connect to database: ${url}`)
})
doesn't check for connection errors, it emits an event if an error is encountered after the initial connection has been made.
As Joe pointed out in the comments, you should handle both the initial connection errors AND errors that may come after it, either with the try/catch syntax or the .catch callback. More info in the docs.

Related

Mongoose parser error while connecting with mongoDB atlas

while trying to connect with my mongoDB atlas using mongoose connect method in node js I'm getting below mentioned parser error, I've checked my DB credentials and there are no special characters (:, /, ?, #, [], #) present in it.
Error:
MongoParseError: URI malformed, cannot be parsed
Code:
const mongoose = require('mongoose');
const DB = process.env.DB.replace('<password>', process.env.DB_PASSWORD);
mongoose
.connect(DB, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
})
.then((con) => {
console.log(con.connections);
console.log('DB connection successful!');
});

How to fix 'Error: querySrv EREFUSED' when connecting to MongoDB Atlas?

I am new to MongoDB 4.0.6 and tried to implement it into my website using Node/Express.js, but when I try to connect to mongodb+srv://${process.env.MONGOUSER}:${process.env.MONGOPASS}#main-03xkr.mongodb.net/main I'm getting this error:
{ Error: querySrv EREFUSED _mongodb._tcp.main-03xkr.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:199:19)
errno: 'EREFUSED',
code: 'EREFUSED',
syscall: 'querySrv',
hostname: '_mongodb._tcp.main-03xkr.mongodb.net' }
I've tried connecting to mongodb://localhost:27017/main, but this does seem work.
Here is the relevant code:
require('dotenv').config();
const mongoose = require('mongoose');
// Database
const uri = `mongodb+srv://${process.env.MONGOUSER}:${process.env.MONGOPASS}#main-03xkr.mongodb.net/main`;
const localURI = 'mongodb://localhost:27017/main';
var Project = require('./models/project');
mongoose.connect(uri, { useNewUrlParser: true });
const db = mongoose.connection;
db.once('open', () => console.log('Successfully connected to MongoDB'));
db.on('error', (e) => console.log(e));
// Routes
app.get('/', (req, res) => {
Project.find({}, (e, projects) => {
if (e) console.log(e);
res.render('home.ejs', {
projects: projects
});
});
});
So does anyone know how to fix this error and maybe explain what is happening here?
If you're encountering this error try to use the older connection string for Node.js 2.2.12 or later:
mongodb://<username>:<password>#main-shard-00-00-03xkr.mongodb.net:27017,main-shard-00-01-03xkr.mongodb.net:27017,main-shard-00-02-03xkr.mongodb.net:27017/main?ssl=true&replicaSet=Main-shard-0&authSource=admin&retryWrites=true
According to MongoDB, SRV is possibly not working due to Mongoose.
I had this same error when I was connecting with Node version 3.0 or later and I resolved it by downgrading to 2.2.12 or later version:
In my case, it's mainly a DNS issue in mac, to resolve it, just add google DNS server under the DNS section in mac book pro settings:
8.8.8.8
4.4.4.4
This error occurs sometimes when you are using MongoDB Atlas and lost your internet connectivity. You will not be able to access your database.
Make sure to change the node version to 2.2.12:
And add IP address:
Pass option { useNewUrlParser: true, useUnifiedTopology: true } to the MongoClient constructor
const uri = "mongodb+srv://${process.env.MONGOUSER}:${process.env.MONGOPASS}#main-03xkr.mongodb.net/main"
mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
.catch(error => console.log(error));
You have undefined in your connection string. I don't know if this is typo or not. But try changing
const uri = `mongodb+srv://undefined:${process.env.MONGOPASS}#main-03xkr.mongodb.net/main`;
to
const uri = `mongodb+srv://${process.env.MONGOUSER}:${process.env.MONGOPASS}#main-03xkr.mongodb.net/main`;
I use MongoAtlas for a project and that string (minus the undefined user) looks correct.
In our case antivirus/firewall is blocking,
Try to disable antivirus/firewall and check again. hope it will work.
Error: querySrv ESERVFAIL _mongodb._tcp.databasename-zcbag.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:202:19) {
errno: 'ESERVFAIL',
code: 'ESERVFAIL',
syscall: 'querySrv',
hostname: '_mongodb._tcp.databasename-zcbag.mongodb.net'
}
If the above code is your output then there is no error in your code. You have to check your network connection. Maybe you have to switch your network from the phone network to another or vice versa.
MongoClient.connect(
"mongodb://USER:PASSWORT#mflix-shard-00-00-r5yfb.mongodb.net/test?ssl=true&replicaSet=mflix-shard-0&authSource=admin&retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true },
)
.catch(err => {
console.error(err.stack)
process.exit(1)
})
.then(async client => {
await MoviesDAO.injectDB(client)
await UsersDAO.injectDB(client)
await CommentsDAO.injectDB(client)
app.listen(port, () => {
console.log(`listening on port ${port}`)
})
})
Maybe can works with MongoClient( not Mongoose )
In my case it was throwing this error due mongodb cluster auto paused because of prolonged inactivity. I just resumed it, then it started properly.
In my case, this error was happening when the DNS configuration in my TP-Link Router was missing.
I've installed OpenWRT firmware on it and forgot to adjust DNS settings.
I was able to open YouTube or any other website because that's not my main router, but could not connect to database.
It was an internet issue, like #Kamesh Kumar Singh said in his answer.
I think that this is not an usual answer for this question, but may help someone.
This error occurs if you are not able to connect to mongoDB Atlas database. Your server runs successfully but you get this error while connecting to database. Make sure your internet connection is good and try again you won't see this error.
I solved mine by going into the MongoDB -> login -> databases -> connect -> connect your application (middle one) -> copy the code -> paste the code into the mongooseDB code in my .JS file:
const mongoose = require('mongoose');
require('dotenv/config');
mongoose
.connect(process.env.THE_MONGO_DB_URL_GOES_HERE_IN_DOTENV_FILE, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log("Database connected!"))
.catch(err => console.log(err));
const PostSchema = mongoose.Schema({
email: String,
password: String
}, {strict: false});
const DataEntry = mongoose.model('n26-users-collection', PostSchema);
module.exports = DataEntry;
"Not in the root folder" scenario:
Create a .env file in the root directory of your project. https://github.com/motdotla/dotenv
One scenario for this error is to create dotenv .env file --NOT-- in the root folder (Under /src for example).
Than this code:
const url = `mongodb+srv://${process.env.DB_USER}:${
process.env.DB_USER_PASSWORD
}#${process.env.DB_CLUSTER}.mongodb.net`;
console.log(url)
output:
mongodb+srv://undefined:undefined#undefined.mongodb.net
So the "undefined" URL connection:
const client = new MongoClient(url);
Throw 3 warnings:
(node:27240) UnhandledPromiseRejectionWarning: Error: querySrv
ENOTFOUND _mongodb._tcp.undefined.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:207:19)
(node:27240) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async
function without a catch block, or by rejecting a promise which was
not handled with .catch(). To terminate the node process on unhandled
promise rejection, use the CLI flag --unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).
(rejection id: 1)
(node:27240) [DEP0018] DeprecationWarning: Unhandled
promise rejections are deprecated. In the future, promise rejections
that are not handled will terminate the Node.js process with a
non-zero exit code.
One more "close" scenario:
.env in the root folder but the file is empty:
Solution
The first step to solve this issue is to console.log(url) and check if process.env returns the correct Connection String.
Related:
dotenv github readme: https://github.com/motdotla/dotenv#readme
Connect to a MongoDB Database Using Node.js
: https://developer.mongodb.com/quickstart/node-connect-mongodb/
In my case, the issue occurred because MongoDB paused my cluster due to over 4 months of inactivity. After I logged in to my account and resumed the activity of the cluster, the issue was immediately resolved.

Node.js and MongoDB Atlas Mongoose Connection Error

I am trying to connect a MongoDB atlas instance to a nodejs/express server :
const mongoose = require("mongoose");
const dbURI =
"mongodb+srv://(url copied from atlas connect)";
const options = {
useNewUrlParser: true,
dbName: "data"
};
mongoose.connect(dbURI, options).then(
() => {
console.log("Database connection established!");
},
err => {
console.log("Error connecting Database instance due to: ", err);
}
);
But I keep get the following error:
MongoNetworkError: connection 5 to cluster ... 27017 closes at TLSSocket. ...
How can I fix this?
Resolved -- Check IP whitelist!

Error connecting to Azure: Illegal character in password with mongoose 5.0.1 but works in 4.13.9

I have a node.js application that is deployed to azure using CosmosDB and the MongoDB API. My application uses mongoose which works seamlessly in 4.13.9.
My application that works connects as follows:
var configDB = require('./config/database');
var mongoose = require('mongoose');
mongoose.connect(configDB.url, { useMongoClient: true } );
mongoose.Promise = global.Promise;
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
the config/database file is defined as follows (changed username, password, DB to protect the innocent):
module.exports = {
'url': 'mongodb://azureusername:azurepassword#myazuredb.documents.azure.com:10255/?ssl=true'
}
Now the problem comes when I install mongoose 5.0.1. I remove the useMongoClient option from the connect and got rid of the promise so my connect code is now:
mongoose.connect(configDB.url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
When this runs I get the following in the console:
(node:21392) UnhandledPromiseRejectionWarning: Unhandled promise
rejection (rejection id: 2): Error: Password contains an illegal
unescaped character
I can even comment out the connection code to where it is only the mongoose.connect and that is what is giving the error. What am I doing wrong? Is there a breaking change in 5.0.1 that I need to account for? As a side note that may or may not be related, I saw some notes about now giving a callback instead of using promises so if someone has an example of how they do that in a Node/Express app that would be great, but it doesn't seem like that's the isee when I'm getting an error reported on the connect about an illegal character.
NOTE: The config file is exactly the same when running against 4.13.9 or 5.0.1 so I know the password is valid and it is not the issue.
For the latest version (v5.0.1) of Mongoose, you'll need to use this syntax to connect to MongoDB like this:
const mongoose = require('mongoose');
mongoose.connect('mongodb://<cosmosdb-username>.documents.azure.com:10255/<databasename>?ssl=true', {
auth: {
user: '<cosmosdb-username>',
password: '<cosmosdb-password>'
}
})
.then(() => console.log('connection successful'))
.catch((err) => console.error(err));
The password for the Azure Cosmos DB instance I got ended with ==, hence the illegal characters message. These characters must be urlencoded.
An equals sign = urlencoded is %3D.
A properly encoded connection string for the password jitsu== could look like mongodb://user:jitsu%3D%3D#localhost:27017/dbname?ssl=false.
Also be aware that the connection strings you get from the Cosmos DB blade in the Azure Portal doesn't include the database name.
To connect to local cosmos db emulator use the following connection method (for mongoose > 5.0.0):
mongoose.connect(
`mongodb://localhost:10255/?ssl=true`,
{
auth: {
user: "localhost",
password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
dbName: "admin"
}
}
);
Or you may also do the following:
const encodedPassword = encodeURIComponent("C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==");
mongoose.connect(`mongodb://localhost:${encodedPassword}#localhost:10255/admin?ssl=true`);
Connection string has following format:
mongodb://username:password#host:port/[database]?ssl=true
and there seems to be some issue with default password character escaping. Thus we encoded it separately.
Add the new url parser as an option { useNewUrlParser: true }
Change you line 3 to:
mongoose.connect(configDB.url, { useMongoClient: true, useNewUrlParser: true } );

mongoose output the error "Error: connection closed"

I stumble upon a curious problem about mongoose connect the mongodb, it generate the detail errors as the following
e:\Mentor_Resources\node\node_twitter_bootstrap>node app
Express server listening on port 3000
Trace: error occure when start to connect dbError: connection closed
at e:\Mentor_Resources\node\node_twitter_bootstrap\server\module\word.js:14:
17
at Connection.open (e:\Mentor_Resources\node\node_twitter_bootstrap\node_mod
ules\mongoose\lib\connection.js:201:5)
at Db.open (e:\Mentor_Resources\node\node_twitter_bootstrap\node_modules\mon
goose\node_modules\mongodb\lib\mongodb\db.js:247:16)
at Server.connect.connectionPool.on.server._serverState (e:\Mentor_Resources
\node\node_twitter_bootstrap\node_modules\mongoose\node_modules\mongodb\lib\mong
odb\connection\server.js:413:7)
at EventEmitter.emit (events.js:115:20)
at connection.on.connectionStatus (e:\Mentor_Resources\node\node_twitter_boo
tstrap\node_modules\mongoose\node_modules\mongodb\lib\mongodb\connection\connect
ion_pool.js:108:15)
at EventEmitter.emit (events.js:91:17)
at Socket.closeHandler (e:\Mentor_Resources\node\node_twitter_bootstrap\node
_modules\mongoose\node_modules\mongodb\lib\mongodb\connection\connection.js:401:
12)
at Socket.EventEmitter.emit (events.js:88:17)
at Socket._destroy.destroyed (net.js:364:10)
the code snippet of mongoose is:
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/word-sentence",function(err) {
if(err)
console.trace('error occure when start to connect db' + err);
});
i am sure the mongodb is open, and i restart mongodb for several times,but the error is still exist, so I reboot my Windows XP , and try again the problem disappear,everything is ok, so I want to know why?
This is a common problem when pooled connections in longer running applications return connection closed.
The mongoose documentation recommends adding keepAlive to the options object you pass into the connect function.
Here's an example (you can remove replset if you're not using this),
// include keep alive for closing connections,
// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
var mongoOptions =
{
db: {safe: true},
server: {
socketOptions: {
keepAlive: 1
}
},
replset: {
rs_name: 'myReplSet',
socketOptions: {
keepAlive: 1
}
}
};
mongoose.connect( YOUR_URI, mongoOptions );
mongoose.connection.on('error', function(err) {
console.log('Mongo Error:\n');
console.log(err);
}).on('open', function() {
console.log('Connection opened');
});
mongoose.connect() Is not accepting any callback functions as you have use in your code i.e.your code snippet of mongoose:
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/word-sentence",function(err) {
if(err)
console.trace('error occurred, when attempted to connect db. Error: ' + err);
});
So, I recommend you to start with this:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/word-sentence');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
// yay connected!
});
Again you cannot expect any arguments in the callback from db.open('open', function cb(){})
I suggest to go through these quick start, mongoose docs - enlightens how you can jump into source code if some conflict is found in the docs & mongodb/mongoose close connection

Resources