Mongoose: Cannot create namespace xxx.xxx in multi-document transaction.

Created on 9 Jul 2018  路  2Comments  路  Source: Automattic/mongoose

Hello, When I tried a simple transaction example for inserting refer to transactions.test.js. and got an error:

{ MongoError: Cannot create namespace test.as in multi-document transaction.
    at ~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:580:63
    at authenticateStragglers (~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:503:16)
    at Connection.messageHandler (~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:539:5)
    at emitMessageHandler (~/test/node_modules/[email protected]@mongodb-core/lib/connection/connection.js:309:10)
    at Socket.<anonymous> (~/test/node_modules/[email protected]@mongodb-core/lib/connection/connection.js:452:17)
    at emitOne (events.js:115:13)
    at Socket.emit (events.js:210:7)
    at addChunk (_stream_readable.js:252:12)
    at readableAddChunk (_stream_readable.js:239:11)
    at Socket.Readable.push (_stream_readable.js:197:10)
    at TCP.onread (net.js:589:20)
  name: 'MongoError',
  message: 'Cannot create namespace test.as in multi-document transaction.',
  operationTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1531118331 },
  ok: 0,
  errmsg: 'Cannot create namespace test.as in multi-document transaction.',
  code: 26,
  codeName: 'NamespaceNotFound',
  '$clusterTime':
   { clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1531118331 },
     signature: { hash: [Object], keyId: 0 } },
  [Symbol(mongoErrorContextSymbol)]: {} }

Here is my code:

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017,localhost:27018,localhost:27019/test?replicaSet=set');
const conn = mongoose.connection;
const Schema = mongoose.Schema;

const schemaA = new Schema({
  name: String
});

const schemaB = new Schema({
  name: String
});

const A = mongoose.model('A', schemaA);
const B = mongoose.model('B', schemaB);

const a = { name: 'Andrew' };
const b = { name: 'Billy' };

async function run() {
  await mongoose.dropDatabase();

  const session = await conn.startSession();
  await session.startTransaction();
  try{
     await A.create([a],{session: session});
     await B.create([b],{session: session});
    await session.commitTransaction();
  } catch(e) {
    console.log(e);
    await session.abortTransaction();
  } finally {
    session.endSession();
  }

  return conn.close();
}

run().catch(console.error);

Mongoose version: 5.2.2
mongodb version: v4.0.0

Thanks

Most helpful comment

This is why our transaction docs explicitly create the collection using createCollection(), because unfortunately transactions can't create collections right now.

Unfortunately, I don't think this is something mongoose can do, because we'd have to send at least one extra database operation (at minimum createCollection()) when creating a session. You should just work around this by calling conn.createCollection('as'). Does that work for you?

All 2 comments

I've found out the reason. Just like mongodb document said:

Operations that affect the database catalog, such as creating or dropping a collection or an index, are not allowed in multi-document transactions. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection. See Restricted Operations.

I think Mongoose should fix it by create the collection before saving a document to an non-exist collection.

This is why our transaction docs explicitly create the collection using createCollection(), because unfortunately transactions can't create collections right now.

Unfortunately, I don't think this is something mongoose can do, because we'd have to send at least one extra database operation (at minimum createCollection()) when creating a session. You should just work around this by calling conn.createCollection('as'). Does that work for you?

Was this page helpful?
0 / 5 - 0 ratings