2

When i run it with a correct password it works fine, only with an incorrect password it throws an uncuaght exception which is not caught by the promise for some reason, and then the app crash

Here is the controller tryCtrl.js:

const connection = require('./tryDB');

connection
  .then(() => console.log('success'))
  .catch((error) => {
    console.error(error);
  });

Here is the model file that access the db tryDB.js

const mongoose = require('mongoose');

require('dotenv').config();

// create connection to db
const uri = process.env.MONGO_URI;

const connection = new Promise((resolve, reject) => {
  mongoose.connect(uri);
  const db = mongoose.connection;
  db.on('error', (error) => {
    reject(error);
  });
  db.once('open', () => {
    resolve(db);
  });
});

module.exports = connection;

when i run it with a false password i expect the expection to be caught, but it breaks the app Here is the error:

node:internal/process/promises:288
        triggerUncaughtException(err, true /* fromPromise */);
        ^

MongoServerError: bad auth : authentication failed
    at Connection.onMessage (C:\Users\israe\Documents\GitHub\my-mongo\node_modules\mongodb\lib\cmap\connection.js:201:30)
    at MessageStream.<anonymous> (C:\Users\israe\Documents\GitHub\my-mongo\node_modules\mongodb\lib\cmap\connection.js:59:60)
    at MessageStream.emit (node:events:513:28)
    at processIncomingData (C:\Users\israe\Documents\GitHub\my-mongo\node_modules\mongodb\lib\cmap\message_stream.js:124:16)
    at MessageStream._write (C:\Users\israe\Documents\GitHub\my-mongo\node_modules\mongodb\lib\cmap\message_stream.js:33:9)
    at writeOrBuffer (node:internal/streams/writable:392:12)
    at _write (node:internal/streams/writable:333:10)
    at Writable.write (node:internal/streams/writable:337:10)
    at TLSSocket.ondata (node:internal/streams/readable:766:22)
    at TLSSocket.emit (node:events:513:28) {   ok: 0,   code: 8000,   codeName: 'AtlasError',   connectionGeneration: 0,  
[Symbol(errorLabels)]: Set(2) { 'HandshakeError', 'ResetPool' } }

Any idea is appreciated

Camilo
  • 6,504
  • 4
  • 39
  • 60

1 Answers1

0

Ideally, you shouldn't export variables that refer to Promises. Exports are meant for functionality or constants which you intend to reuse later. You should restructure your connection function, to return a Promise instead, like this:

const mongoose = require('mongoose');

require('dotenv').config();

// create connection to db
const uri = process.env.MONGO_URI;

const connection = () => new Promise((resolve, reject) => {
  mongoose.connect(uri);
  const db = mongoose.connection;
  db.on('error', (error) => {
    reject(error);
  });
  db.once('open', () => {
    resolve(db);
  });
});

module.exports = connection;

Now your controller becomes like this:

const connection = require('./tryDB');

connection()
  .then(() => console.log('success'))
  .catch((error) => {
    console.error(error);
  });

Note, that I have called the connection function first, then the promise functions are chained.

UPDATE: This is an uncaught exception. To catch it, you can add process.on event handlers. In your app.js file, like this:

process
  .on('unhandledRejection', (reason, p) => {
    console.error(reason, 'Unhandled Rejection at Promise', p);
  })
  .on('uncaughtException', err => {
    console.error(err, 'Uncaught Exception thrown');
  });

Note this is not the recommended way, ideally, you should let the application stop on such errors. Also, you can try setting mongoose.Promise = global.Promise; as suggested by the creator of mongoose here.

Charchit Kapoor
  • 8,934
  • 2
  • 8
  • 24