{"record":{"id":"390d00d99dd61300","repo":"Automattic/mongoose","slug":"connection-doclose-unimplemented-by-driver","errorCode":null,"errorMessage":"Connection#doClose unimplemented by driver","messagePattern":"Connection#doClose unimplemented by driver","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/connection.js","lineNumber":1320,"sourceCode":"          if (destroy && this.base.connections.indexOf(conn) !== -1) {\n            this.base.connections.splice(this.base.connections.indexOf(conn), 1);\n          }\n          resolve();\n        });\n      });\n  }\n\n  return this;\n};\n\n/**\n * Abstract method that drivers must implement.\n *\n * @api private\n */\n\nConnection.prototype.doClose = function doClose() {\n  throw new MongooseError('Connection#doClose unimplemented by driver');\n};\n\n/**\n * Called when the connection closes\n *\n * @emits \"close\"\n * @api private\n */\n\nConnection.prototype.onClose = function onClose(force) {\n  this.readyState = STATES.disconnected;\n\n  // avoid having the collection subscribe to our event emitter\n  // to prevent 0.3 warning\n  for (const i in this.collections) {\n    if (Object.hasOwn(this.collections, i)) {\n      this.collections[i].onClose(force);\n    }","sourceCodeStart":1302,"sourceCodeEnd":1338,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/connection.js#L1302-L1338","documentation":"doClose() is the abstract hook that driver adapters must implement; Connection.prototype.close() and destroy() delegate the actual socket teardown to it. The bundled node-mongodb-native driver overrides it, so a normal mongoose connection never sees this error — it appears only when a custom Connection subclass (mock, alternate driver, test double) forgot to override doClose and someone calls close() or destroy().","triggerScenarios":"await conn.close() or await conn.destroy() on a connection whose class implements some driver methods but not doClose; closing a bare `new Connection()` instance.","commonSituations":"Writing unit-test fakes of Connection; custom driver integrations that partially implement the adapter interface; accidentally instantiating the base Connection class.","solutions":["Create connections via mongoose.connect()/mongoose.createConnection() so the native driver's class is used","If you maintain a custom connection class, implement doClose(force) on it","In tests, stub the hook: conn.doClose = async () => {}"],"exampleFix":"// before\nclass FakeConnection extends Connection { /* forgot doClose */ }\nawait fakeConn.close(); // throws\n\n// after\nclass FakeConnection extends Connection {\n  async doClose(force) { /* close your transport */ return this; }\n}\nawait fakeConn.close();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await conn.close();\n} catch (err) {\n  if (/doClose unimplemented/.test(err.message)) {\n    await conn.client?.close?.(); // close the underlying driver client directly\n  } else {\n    throw err;\n  }\n}","preventionTips":["Never ship a Connection subclass that only partially implements the driver adapter interface (doOpen, doClose, setClient, createClient, listDatabases, ...)","In unit tests, stub doClose instead of exercising real close() on a fake","Only obtain connections from mongoose.connect()/createConnection() in production code"],"tags":["driver","close","abstract-method","custom-driver"],"backgroundTag":"driver-method-unimplemented","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}