{"record":{"id":"8933b292807439bd","repo":"Automattic/mongoose","slug":"connection-has-been-closed-and-destroyed-and-cann","errorCode":null,"errorMessage":"Connection has been closed and destroyed, and cannot be used for re-opening the connection. Please create a new connection with `mongoose.createConnection()` or `mongoose.connect()`.","messagePattern":"Connection has been closed and destroyed, and cannot be used for re-opening the connection\\. Please create a new connection with `mongoose\\.createConnection\\(\\)` or `mongoose\\.connect\\(\\)`\\.","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/drivers/node-mongodb-native/connection.js","lineNumber":240,"sourceCode":"NativeConnection.prototype.listDatabases = async function listDatabases() {\n  await this._waitForConnect();\n\n  return await this.db.admin().listDatabases();\n};\n\n/*!\n * ignore\n */\n\nNativeConnection.prototype.createClient = async function createClient(uri, options) {\n  if (typeof uri !== 'string') {\n    throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +\n      `string, got \"${typeof uri}\". Make sure the first parameter to ` +\n      '`mongoose.connect()` or `mongoose.createConnection()` is a string.');\n  }\n\n  if (this._destroyCalled) {\n    throw new MongooseError(\n      'Connection has been closed and destroyed, and cannot be used for re-opening the connection. ' +\n      'Please create a new connection with `mongoose.createConnection()` or `mongoose.connect()`.'\n    );\n  }\n\n  if (this.readyState === STATES.connecting || this.readyState === STATES.connected) {\n    if (this._connectionString !== uri) {\n      throw new MongooseError('Can\\'t call `openUri()` on an active connection with ' +\n        'different connection strings. Make sure you aren\\'t calling `mongoose.connect()` ' +\n        'multiple times. See: https://mongoosejs.com/docs/connections.html#multiple_connections');\n    }\n  }\n\n  options = processConnectionOptions(uri, options);\n\n  if (options) {\n\n    const autoIndex = options.config?.autoIndex ?? options.autoIndex;","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/drivers/node-mongodb-native/connection.js#L222-L258","documentation":"A connection closed with destroy() (not close()) is marked with _destroyCalled and is permanently unusable. createClient()/openUri() checks that flag and throws this MongooseError: a destroyed connection may hold torn-down state, so Mongoose requires a new connection object rather than resurrecting the old one.","triggerScenarios":"await conn.destroy(); await conn.openUri(uri); - or mongoose.connection.destroy() followed by mongoose.connect() reusing the same default connection object.","commonSituations":"Test suites that destroy connections in after() and reconnect in the next file using the cached default connection; app shutdown/restart logic inside a long-lived process (electron, worker respawn) reusing the mongoose default connection.","solutions":["Create a fresh connection instead of reopening: const conn = await mongoose.createConnection(uri).asPromise().","Use close() instead of destroy() when you intend to reopen the same connection later.","In tests, build an isolated connection per suite with createConnection() instead of reusing the global one."],"exampleFix":"// before\nawait conn.destroy();\nawait conn.openUri(uri); // throws: destroyed connection cannot reopen\n\n// after (option 1: close instead of destroy when reopening later)\nawait conn.close();\nawait conn.openUri(uri);\n// after (option 2: fresh connection object)\nconst conn2 = await mongoose.createConnection(uri).asPromise();","handlingStrategy":"fallback","validationCode":"// track lifecycle yourself and hand out a usable connection\nlet destroyed = false;\nasync function getConnection(uri) {\n  if (destroyed) {\n    return mongoose.createConnection(uri); // fresh object\n  }\n  return mongoose.connection.readyState === 1\n    ? mongoose.connection\n    : mongoose.connect(uri);\n}\n// mark on teardown\nasync function teardown() {\n  destroyed = true;\n  await mongoose.connection.destroy();\n}","typeGuard":null,"tryCatchPattern":"try {\n  await conn.openUri(uri);\n} catch (err) {\n  if (err instanceof mongoose.MongooseError && err.message.includes('closed and destroyed')) {\n    conn = await mongoose.createConnection(uri).asPromise(); // fresh connection, continue\n    return conn;\n  }\n  throw err;\n}","preventionTips":["Reserve destroy() for final teardown (process exit); use close() for reopenable shutdowns.","In test suites, create an isolated connection per suite with createConnection() instead of reusing the global default.","Wrap connection lifecycle in a small manager that returns either the live connection or a new one."],"tags":["mongoose","connection","destroy","lifecycle","restart"],"backgroundTag":"connection-already-destroyed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}