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
- 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.
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
- 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.
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
- Connection#createClient not implemented by driver
- Cannot call `${this.name}.${i}()` before initial connection
- No connections to database "${name}" found
- Cannot call `setClient()` on a connection that is already co
- `useConnection()` requires a Mongoose connection.
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/8933b292807439bd.
Report an issue: GitHub.