Automattic/mongoose · error · MongooseError

Connection has been closed and destroyed, and cannot be used

Error message

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()`.

What it means

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.

Source

Thrown at lib/drivers/node-mongodb-native/connection.js:240

NativeConnection.prototype.listDatabases = async function listDatabases() {
  await this._waitForConnect();

  return await this.db.admin().listDatabases();
};

/*!
 * ignore
 */

NativeConnection.prototype.createClient = async function createClient(uri, options) {
  if (typeof uri !== 'string') {
    throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
      `string, got "${typeof uri}". Make sure the first parameter to ` +
      '`mongoose.connect()` or `mongoose.createConnection()` is a string.');
  }

  if (this._destroyCalled) {
    throw new MongooseError(
      '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()`.'
    );
  }

  if (this.readyState === STATES.connecting || this.readyState === STATES.connected) {
    if (this._connectionString !== uri) {
      throw new MongooseError('Can\'t call `openUri()` on an active connection with ' +
        'different connection strings. Make sure you aren\'t calling `mongoose.connect()` ' +
        'multiple times. See: https://mongoosejs.com/docs/connections.html#multiple_connections');
    }
  }

  options = processConnectionOptions(uri, options);

  if (options) {

    const autoIndex = options.config?.autoIndex ?? options.autoIndex;

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Create a fresh connection instead of reopening: const conn = await mongoose.createConnection(uri).asPromise().
  2. Use close() instead of destroy() when you intend to reopen the same connection later.
  3. In tests, build an isolated connection per suite with createConnection() instead of reusing the global one.

Example fix

// before
await conn.destroy();
await conn.openUri(uri); // throws: destroyed connection cannot reopen

// after (option 1: close instead of destroy when reopening later)
await conn.close();
await conn.openUri(uri);
// after (option 2: fresh connection object)
const conn2 = await mongoose.createConnection(uri).asPromise();
Defensive patterns

Strategy: fallback

Validate before calling

// track lifecycle yourself and hand out a usable connection
let destroyed = false;
async function getConnection(uri) {
  if (destroyed) {
    return mongoose.createConnection(uri); // fresh object
  }
  return mongoose.connection.readyState === 1
    ? mongoose.connection
    : mongoose.connect(uri);
}
// mark on teardown
async function teardown() {
  destroyed = true;
  await mongoose.connection.destroy();
}

Try / catch

try {
  await conn.openUri(uri);
} catch (err) {
  if (err instanceof mongoose.MongooseError && err.message.includes('closed and destroyed')) {
    conn = await mongoose.createConnection(uri).asPromise(); // fresh connection, continue
    return conn;
  }
  throw err;
}

Prevention

When it happens

Trigger: await conn.destroy(); await conn.openUri(uri); - or mongoose.connection.destroy() followed by mongoose.connect() reusing the same default connection object.

Common situations: 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.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/8933b292807439bd. Report an issue: GitHub.