Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to catch MongoNetworkError: connect ECONNREFUSED in Node when using mongoose.createConnection() #14455

Closed
2 tasks done
intersides opened this issue Mar 21, 2024 · 6 comments
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary Stale

Comments

@intersides
Copy link

intersides commented Mar 21, 2024

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

8.0.0

Node.js version

21

MongoDB server version

5.0

Typescript version (if applicable)

No response

Description

on a lost connection there is no clear way to trap MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
thrown from: node_modules/mongodb/lib/sdam/topology.js:276:34

The connection is created as

try{
  mongooseConnection = mongoose.createConnection(mongoUri, {
      serverSelectionTimeoutMS: 5000
  });
       ....
}
 catch(e){
    console.error(e);
}

Steps to Reproduce

  • create a database connection with a mongo instance that can be shut down at will. After connection all the relative callbacks are triggered (connected, open, etc..).
  • shut down the mongo db database.
  • callbacks are triggered (disconnect). connection.readystate changes to 0.
  • wait into this dosconnected mode for about 10 seconds

The following appears:
MongoNetworkError: connection 1 to 192.168.32.2:27017 closed
at Connection.onClose (/opt/backend/node_modules/mongodb/lib/cmap/connection.js:124:28)
at Socket. (/opt/backend/node_modules/mongodb/lib/cmap/connection.js:66:46)
at Socket.emit (node:events:519:28)
at TCP. (node:net:337:12) {
[Symbol(errorLabels)]: Set(0) {},
[cause]: undefined

After 2 more seconds the disconnect callback is triggered and the following appear:

MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
backend | 13:31:20 0|main | at EventTarget. (/opt/backend/node_modules/mongodb/lib/sdam/topology.js:276:34)
backend | 13:31:20 0|main | at [nodejs.internal.kHybridDispatch] (node:internal/event_target:822:20)
backend | 13:31:20 0|main | at EventTarget.dispatchEvent (node:internal/event_target:757:26)
backend | 13:31:20 0|main | at abortSignal (node:internal/abort_controller:374:10)
backend | 13:31:20 0|main | at TimeoutController.abort (node:internal/abort_controller:396:5)
backend | 13:31:20 0|main | at Timeout. (/opt/backend/node_modules/mongodb/lib/utils.js:1011:92)
backend | 13:31:20 0|main | at listOnTimeout (node:internal/timers:573:17)
backend | 13:31:20 0|main | at process.processTimers (node:internal/timers:514:7) {
backend | 13:31:20 0|main | reason: TopologyDescription {
backend | 13:31:20 0|main | type: 'Unknown',
backend | 13:31:20 0|main | servers: Map(1) { 'mongo1:27017' => [ServerDescription] },
backend | 13:31:20 0|main | stale: false,
backend | 13:31:20 0|main | compatible: true,
backend | 13:31:20 0|main | heartbeatFrequencyMS: 10000,
backend | 13:31:20 0|main | localThresholdMS: 15,
backend | 13:31:20 0|main | setName: null,
backend | 13:31:20 0|main | maxElectionId: null,
backend | 13:31:20 0|main | maxSetVersion: null,
backend | 13:31:20 0|main | commonWireVersion: 0,
backend | 13:31:20 0|main | logicalSessionTimeoutMinutes: null
backend | 13:31:20 0|main | },
backend | 13:31:20 0|main | code: undefined,
backend | 13:31:20 0|main | [Symbol(errorLabels)]: Set(0) {},
backend | 13:31:20 0|main | [cause]: MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017
backend | 13:31:20 0|main | at connectionFailureError (/opt/backend/node_modules/mongodb/lib/cmap/connect.js:379:20)
backend | 13:31:20 0|main | at Socket. (/opt/backend/node_modules/mongodb/lib/cmap/connect.js:285:22)
at Object.onceWrapper (node:events:634:26)
at Socket.emit (node:events:519:28)
at emitErrorNT (node:internal/streams/destroy:169:8)
at emitErrorCloseNT (node:internal/streams/destroy:128:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
[Symbol(errorLabels)]: Set(1) { 'ResetPool' },
[cause]: Error: connect ECONNREFUSED 127.0.0.1:27017
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 27017
}
}
}

Expected Behavior

try{
mongooseConnection = mongoose.createConnection(mongoUri, {
serverSelectionTimeoutMS: 5000
});
....
}
catch(e){
console.error(e);
}

The Error should have been reported in the catch block

@IslandRhythms
Copy link
Collaborator

Try adding .catch(e => console.log(e)) to the create connection code instead of wrapping it in a try catch and see if that helps.

@intersides
Copy link
Author

No, also asPromise() the mongoose.createConnection the catch doesn't get called.

mongoose.createConnection(params.url, { serverSelectionTimeoutMS: 5000 }).asPromise() .then(_connection=>{ ... }) .catch(e => console.log(e));

@vkarpov15 vkarpov15 added this to the 8.2.4 milestone Mar 28, 2024
@vkarpov15 vkarpov15 added the needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue label Mar 28, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.2.4, 8.2.5 Mar 28, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.3.1, 8.3.2 Apr 5, 2024
@vkarpov15
Copy link
Collaborator

Once initial connection is completed, await mongoose.createConnection().asPromise() will not throw an error if the connection is later interrupted.

Given that you aren't properly handling errors in your original post (missing await and asPromise() with createConnection()), the issue is most likely that you aren't correctly handling errors in other parts of your code as well. For example, the following code will throw an uncaught error if the MongoDB server stops:

try {
  TestModel.findOne();
} catch (err) {
  handleError(err);
}

TestModel.findOne() is an asynchronous operation and returns a thenable, try/catch won't catch errors unless you await as follows

try {
  await TestModel.findOne();
} catch (err) {
  handleError(err);
}

@vkarpov15 vkarpov15 removed this from the 8.3.2 milestone Apr 10, 2024
@vkarpov15 vkarpov15 added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary and removed needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue labels Apr 10, 2024
Copy link

This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days

@github-actions github-actions bot added the Stale label Apr 25, 2024
Copy link

github-actions bot commented May 1, 2024

This issue was closed because it has been inactive for 19 days and has been marked as stale.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale May 1, 2024
@sadeghhosseini
Copy link

This might help:

process.on('unhandledRejection', (error) => {
        if (error instanceof mongoose.mongo.MongoNetworkError) {
            console.log(error);
        } else {
	    console.log('unhandled rejection: ', error);
	    throw new Error(); // so that other types of unhandled exceptions crash the server!
        }
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary Stale
Projects
None yet
Development

No branches or pull requests

4 participants