Mongoose: Deprecation Warning

Created on 1 Jul 2016  路  79Comments  路  Source: Automattic/mongoose

I'm getting this warning

(node:3341) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

after I do

driver.createCar({
          carName: 'jeep',
          availableSeats: 4,
        }, callback);

driver is an instance of Driver class

const carSchema = new Schema({
  carName: String,
  availableSeats: Number,
  createdOn: { type: Date, default: Date.now },
});
const driverSchema = new Schema({
  email: String,
  name: String,
  city: String,
  phoneNumber: String,
  cars: [carSchema],
  userId: {
    type: Schema.Types.ObjectId,
    required: true,
  },
  createdOn: { type: Date, default: Date.now },
});
const DriverModel = mongoose.model('Driver', driverSchema);

class Driver extends DriverModel {
  getCurrentDate() {
    return moment().format();
  }
  create(cb) {
    // save driver
    this.createdOn = this.getCurrentDate();
    this.save(cb);
  }
  remove(cb) {
    super.remove({
      _id: this._id,
    }, cb);
  }
  createCar(carData, cb) {
    this.cars.push(carData);
    this.save(cb);
  }
  getCars() {
    return this.cars;
  }
}

any thoughts about what Im doing wrong?

help

Most helpful comment

I solved that warning doing

mongoose.Promise = global.Promise;

Right before calling mongoose.connect

// connect to mongo function
core.connect = function connect(opts) {
  mongoose.Promise = global.Promise;
  mongoose.connect(`mongodb://${opts.server}:${opts.port}/${opts.db}`);
  return mongoose.connection;
};

All 79 comments

Hmm are you using promises anywhere? You shouldn't be getting this warning unless you use promises...

nop I'm not using promises

I've just started to get this issue too. Not using promises that I know of!

I solved that warning doing

mongoose.Promise = global.Promise;

Right before calling mongoose.connect

// connect to mongo function
core.connect = function connect(opts) {
  mongoose.Promise = global.Promise;
  mongoose.connect(`mongodb://${opts.server}:${opts.port}/${opts.db}`);
  return mongoose.connection;
};

Yeah this warning is supposed to tell you to change mongooses default promise lib if you're using promises, but it shouldn't happen unless you call .then somewhere

I'm getting it but I'm only getting it where I save a object then modify it in the callback and save again

I've tried the @SAudelOG approach to assign a promise to mongoose before mongoose connect but I still receiving this error

I'm using async functions es7, and my code is blocked when I try to Model.findOne({})

The solution @SAudelOG provides works. Like @IrishAdo I'm only getting this when saving an object also. Perhaps it is because of one of the mongoose plugins I'm using using Bluebird promise library.

Here is a list of dependencies I'm using

  "dependencies": {
    "async": "^2.0.0-rc.6",
    "body-parser": "^1.15.0",
    "bower": "^1.7.7",
    "compression": "^1.6.1",
    "connect-mongo": "^1.2.1",
    "consolidate": "^0.14.1",
    "cookie-parser": "^1.4.3",
    "express": "^4.13.4",
    "express-jwt": "^3.4.0",
    "express-session": "^1.13.0",
    "express-validator": "^2.20.8",
    "faker": "^3.1.0",
    "http-errors": "^1.5.0",
    "jsonwebtoken": "^7.0.1",
    "lodash": "^4.13.1",
    "method-override": "^2.3.5",
    "mongoose": "^4.4.3",
    "mongoose-beautiful-unique-validation": "^3.0.0",
    "mongoose-delete": "^0.3.3",
    "mongoose-validator": "^1.2.5",
    "morgan": "^1.6.1",
    "passport": "^0.3.2",
    "passport-local": "^1.0.0",
    "swig": "^1.4.2"
  }

I'm not using plugins nor promises and getting this warning as well (on [email protected]).

Running my app with "--trace-deprecation" I've got:

Trace: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead:
http://mongoosejs.com/docs/promises.html
    at Object.exports._printDeprecationMessage (internal/util.js:30:13)
    at Promise.deprecated [as then] (internal/util.js:54:22)
    at fnWrapper (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:188:11)
    at EmbeddedDocument.Object.defineProperty.value.fn (.\node_modules\mongoose\lib\schema.js:219:11)
    at _next (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:62:30)
    at fnWrapper (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:186:18)
    at EmbeddedDocument.Object.defineProperty.value.fn (.\node_modules\mongoose\lib\schema.js:173:18)
    at EmbeddedDocument._next (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:62:30)
    at EmbeddedDocument.proto.(anonymous function) [as $__original_save] (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:108:20)
    at .\node_modules\mongoose\lib\document.js:1917:24
    at new Promise.ES6 (.\node_modules\mongoose\lib\promise.js:45:3)
    at EmbeddedDocument.wrappedPointCut [as save] (.\node_modules\mongoose\lib\document.js:1893:14)
    at async.each.i (.\node_modules\mongoose\lib\schema.js:225:18)
    at .\node_modules\async\lib\async.js:181:20
    at Object.async.forEachOf.async.eachOf (.\node_modules\async\lib\async.js:233:13)
    at Object.async.forEach.async.each (.\node_modules\async\lib\async.js:209:22)
    at model.Object.defineProperty.value.fn (.\node_modules\mongoose\lib\schema.js:223:15)
    at _next (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:62:30)
    at fnWrapper (.\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:186:18)
    at .\node_modules\mongoose\lib\schema.js:200:17
    at .\node_modules\mongoose\node_modules\kareem\index.js:127:16
    at nextTickCallbackWith0Args (node.js:420:9)
    at process._tickDomainCallback (node.js:390:13)

I have the same issue, if it's any help it is specifically triggered when I try to create documents which have an array of subdocuments inside them, something like:

var data = {
  field: 'value',
  another_field: [{subdocfield1: 'value', subdocfield2: 'value'}]
} 

mySchema.create(data, cb)

It does not occur with other collections that do not have subdocs, it doesn't even happen if I issue the create statement without the subdoc data, like this:

var data = {
  field: 'value'
} 

mySchema.create(data, cb)

_Note:_ mongoose.Promise = global.Promise did solve the warning problem for me though

Experiencing same depreciation warning when I use remove() on a document. I am not using promises here or anywhere else in my code.

I just got this error when using Model.create(objects, callback);, perhaps this fix hasn't been published to npm yet?

Getting this, glad to read it is not alarming. I shall keep a closer look into this to help debugging when it happens.

Getting this as well, and I'm not using mongoose promises anywhere.

I was able to trace it back to a model.save call inside a callback of the library on-headers, and the model was created outside the callback, before it was called, in case it helps anyone. Putting both the model creation and save call within the callback makes no difference.

Facing this issue on node v4.4.6 whereas on v4.4.2 this seems to work

@SKatiyar code sample please

same with me, getting this message after invoking save() method, enough for me to care

This works! Before mongoose.connect(MONGO_URI); add mongoose.Promise = global.Promise;

The following code is enough to reproduce on my end:

const mongoose = require('mongoose');
const schema = new mongoose.Schema({
  data: { type: Number }
});
const Model = mongoose.model('schema', schema);
mongoose.connect('mongodb://127.0.0.1:27017/somedatabase');
const newModel = new Model({ data: 1 });
const save = newModel.save(() => {
  console.log('saved model');
});
console.log(typeof save.then); //=> 'function'

Strange thing I can see here is that using newModel.save(callback) still returns a promise (or I'm assuming that's a promise, since the type of .then is 'function'). Is that expected behavior?

Here are my versions:
Node: v6.3.1
Mongoose: v4.5.8

Let me know if you need any other info from me.

@dvlsg yes that's expected behavior currently, save will always return a promise even if you pass a callback

Well, I guess that would at least explain why people are seeing the promise warning even when they don't think they're using promises.

That explain everything.. I'm just a bit paranoid and wanted to get rid all of the warning 馃拑

It's my fault, yup .save() returns a promise so this is expected, but still, warning made me wonder. http://mongoosejs.com/docs/promises.html (just had to read first paragraph 馃幈)

So .save() returns a promise but you shouldn't get this warning unless you call .then(). If you get this warning without calling .then() in your code, that means mongoose is using a promise somewhere where it shouldn't, so please open a separate issue with code samples :+1:

IMHO, this message should be an error ("things don't work") rather than a warning ("pay attention but it should work"), since it is actually returned as error in the callback.

I ran into this problem and aModel.save() method didn't work to put into MongoDB. It took some time to root cause to this problem. After apply "mongoose.Promise = global.Promise;", it succeeded.

I was using "mongoose": "^4.5.9".

Save should work fine with the default promise lib, can you provide a code sample?

@vkarpov15

You're right. I just tried and failed to recreate from scratch the blocking save result with the warning.

I'm not sure if it is related to other code in my project. need some time to check. Please ignore before I find out the cause.

I for me this log pops up in the console whenever I use .then(), it doesn't matter if it is used with a mongoose object or any other object not related to mongoose

So, as per the docs, I am passing in

'use strict';
var Promise = require('bluebird');

// Development specific configuration
// ==================================
module.exports = {
  // MongoDB connection options
  mongo: {
    uri: 'mongodb://localhost/fullstack-dev',
    options: {
      promiseLibrary: Promise
    }
  },
  // .. other config
};

Then in my main file doing

'use strict';

// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
process.env.BLUEBIRD_DEBUG = 1;
var mongoose = require('mongoose');
var config = require(path.join(__dirname, 'server', 'config', 'environment'));

// Connect to database
var db = mongoose.connect(config.mongo.uri, config.mongo.options);
mongoose.connection.on('error', function(err) {
  console.error('MongoDB connection error: ' + err);
  process.exit(-1);
});

And I am still getting the deprecation warning when doing query.exec. Any suggestions on what I am doing wrong?
[Edit: Adding mongoose and bluebird versions]
I am using mongoose ^4.6.1, bluebird ^3.4.6

I am getting warning as well on mongoose 4.6.1 and node 4.4.5

    var mongoose = require('mongoose');
    mongoose.Promise = global.Promise;
    mongoose.connect(dbConfig);
    var connection = mongoose.connection;

@manu29d looks like you're not setting mongoose.Promise = bluebird

@vkarpov15 I think I am. I declared var Promise = at the start of the config script and then promiseLibrary: Promise later on. (Look at the first code snippet in the examples)

Also, I tried writing promiseLibrary: require('bluebird') as is given in the docs.

I don't see mongoose.Promise = require('bluebird') anywhere in the code sample you provided. var Promise = require('bluebird'); is _not_ right.

@vkarpov15 I am referring to http://mongoosejs.com/docs/promises.html#promises-for-the-mongodb-driver

Is that still valid? I haven't got the time to check the code whether this option(promiseLibrary) is supported in the config still or has been removed.

Setting mongoose.Promise = global.Promise works though.

mongoose.Promise = global.Promise
before mongoose.connect works for me too.

I am not using promises and calling mongoose.Promise = global.Promise before connect works.

@manu29d those docs are correct, however, if you actually read them, you'll see that the promiseLibrary option only affects the underlying mongodb driver, _not_ mongoose models.

@zubair-farooqui-10p the below script doesn't trigger the warning for me in 4.5.9 or 4.6.3:

'use strict';

Error.stackTraceLimit = Infinity;

var assert = require('assert');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/gh4291');
mongoose.set('debug', true);

var connection = mongoose.connection;

It's really annoying you have to add this additional line, is there a way for mongoose to fix it in their internal library? Thanks!

Not in general, because the way mongoose's promise lib switching mechanism works is quite different from how the mongodb driver's is. In mongoose it's just a property that you can set on the mongoose global object at anytime, whereas in the mongodb driver it's a connection option, so different connections can have different promise libs but you can only set the promise lib when you're connecting, not afterward. It's not really a priority to reconcile these differences atm.

Why this happens when saving document that has array of strings, could anybody elaborate

I also get it after just calling .createConnecton(). The funny thing I do use Q... BUT! But I prefer to do it after I establish a connection, because I (and I'm pretty sure everybody) prefer to do it in the var declaration block. i.e.

var mongoose = require('mongoose'),
        connection1 = mongoose.createConnection(dbConn1Str),
        connection2 = mongoose.createConnection(dbConn2Str)
;
mongoose.Promise = Q.makePromise;

Instead, to get rid of this warning I'm forced to do:

var mongoose = require('mongoose'),
        connection1, connection2
;
mongoose.Promise = Q.makePromise;
connection1 = mongoose.createConnection(dbConn1Str)
connection2 = mongoose.createConnection(dbConn2Str)

Not a big deal, but srsly...

Yeah that's the way to go. Mongoose 4.x will use mpromise until you tell it not to.

I see this when using regular find() call with query helper. I don't use then anywhere.

BookStore.find().byUsingQueryHelper(1,2,3).lean().exec(function (err, docs) { ... })

Log:

Mongoose: bookstores.find({ location: { '$near': [ 28.742712943610545, -13.865369983731426 ], '$maxDistance': 0.0012556898446083817 } }, { limit: 10, fields: undefined })

(node:82366) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

@pronebird unfortunately that's how exec() works internally, callbacks to exec() actually go through a promise. Just do mongoose.Promise = global.Promise and you shouldn't get that warning anymore.

@pronebird I got the same error when post, and I found out that my schema has a default value as shown below and does not match my posted value below
role: {
type: String,
enum: ['Client', 'Admin'],
default: 'Client'
}
I post role:admin and it should be Admin
hope this answer help someone. thanks

@Muhammedalbayati I don't think your issue has anything to do with this particular issue? It's just a warning issued by Mongoose regarding promises.

@varunjayaraman you are right, I should mention the following
the warning
DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

goes away by adding mongoose.Promise = global.Promise; before connecting to the db
mongoose.connect('mongodb://localhost:27017/mydb');

@Muhammedalbayati I think @vkarpov15 explained why this warning appears. Mongoose uses promises internally within exec.

ES6 "yiled" just not work with doc.save method after i upgrade mongoose to v.4.7.7.
Finally it is just because mongoose.Promise = global.Promise. After i remove this it still warning

Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead:

I guess [email protected] has it own promise module. Is that right??
Does anyone know it?

It is mongoose add an es6-promise lib.

So stupid issue!

PS: 袟邪褋褍薪褜 褋械斜械 胁 锌懈蟹写褍 褝褌芯褌 胁邪褉薪懈薪谐 械斜褍褔懈泄!

as a fellow Russian speaker I apologize for the behavior this lesser being has displayed an urge you not to translate what it has written here.

@vkarpov15 I have tried both mongoose.Promise = global.Promise; and mongoose.Promise = require('bluebird'); .

Unfortunately, I am still receiving the deprecation warning.

_Is there something I am doing wrong?_

const mongoose = require('mongoose');

mongoose.Promise = global.Promise;

mongoose.connect('mongodb://localhost/users_test');

mongoose.connection
  .once('open', () => {
    console.log('connectecd to db')
  })
  .on('error', (err) => {
    console.warn('Warning', err)
  });

@protoEvangelium Are you importing mongoose elsewhere in your app? Is this the first time mongoose is being used or is this file imported into another file?

Also what version of mongoose /node are you using?

@varunjayaraman This file is not being imported anywhere else. However, I am importing mongoose in my user.js schema file and then using that User schema in some of my tests.

const mongoose = require('mongoose')
const Schema = mongoose.Schema
const UserSchema = new Schema({
  name: String,
})
const User = mongoose.model('user', UserSchema)
module.exports = User

node v7.0.0
mongoose v4.8.1

@protoEvangelium are you getting the warning in your app or only in your tests?

I've had the same problem once - the culprit was another module, that used it's own mongoose dependency. Such modules have something like "mongoose": "^4.1.1" in their package.json, but since these modules are updated on an annual basis (if at all) - they lack the promise config part. @protoEvangelium are you using any other modules?

@SAudelOG Thanks for the answer

@varunjayaraman I have only begun to test adding users to Mongo using Mongoose and Mocha. It is a barebones project so far.

@Spown I am using:
"mocha": "^3.2.0", "mongoose": "^4.8.1", "nodemon": "^1.11.0"

Thanks :)

@protoEvangelium wait a minute, did you try this?

const mongoose = require('mongoose')
mongoose.Promise = global.Promise // <--
const Schema = mongoose.Schema
const UserSchema = new Schema({
  name: String,
})
const User = mongoose.model('user', UserSchema)
module.exports = User

if you create a model from a mongoose instance who's promise wasn't redefined - every query on this model would throw the warning.

@Spown

I happened across this thread at the right time. I was receiving the same warning anytime I was saving information. Turns out I was creating a model from an instance of mongoose and was not redefining it. Requiring bluebird and setting it to mongoose.Promise resolved the error message.

Thanks so much!

@Spown Thank you sir! That was the issue. Interestingly, I defined mongoose.Promise = global.Promise; in my test_helper.js file right before connecting to Mongoose. I switched the mongoose.Promise = global.Promise; over to my file where I defined the Schema and it works!!!! No more deprecation warning 馃憤

const mongoose = require('mongoose')
mongoose.Promise = global.Promise;
const Schema = mongoose.Schema

I'm getting this issue when using "populatable" virtuals in my schemas. Running my app with --trace-deprecations, you can see the culprit:

(node:8846) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
    at model.wrappedPointCut [as init] (/Users/fleavamini/Projects/stellium/stellium-express/node_modules/mongoose/lib/services/model/applyHooks.js:141:26)
    at completeMany (/Users/fleavamini/Projects/stellium/stellium-express/node_modules/mongoose/lib/query.js:1254:12)
    at Immediate.cb (/Users/fleavamini/Projects/stellium/stellium-express/node_modules/mongoose/lib/query.js:1117:13)
    at Immediate.<anonymous> (/Users/fleavamini/Projects/stellium/stellium-express/node_modules/mquery/lib/utils.js:137:16)
    at runCallback (timers.js:651:20)
    at tryOnImmediate (timers.js:624:5)
    at processImmediate [as _immediateCallback] (timers.js:596:5)

I have set the promise (note I'm using TypeScript):

import * as mongoose from "mongoose";
(<any>mongoose).Promise = global.Promise;
mongoose.connect('mongodb://localhost/blah')

Any ideas? Should I set the promise on every model that uses "populatable" virtuals? Hold on, I'm actually going to try that and come back with how it went.

Okay, after some tinkering, I figured out that I still need to set the Promise on my Schema even if I have set it in the index of my server.

In my case, the website_pages collection was the first collection to ever get queried by my system, setting the mongoose.Promise to global.Promise on this schema alone has fixed the issue and I wasn't required to set it in all Schemas.

Why not to use ES6 Promises? Aren't they available everywhere now?

mongoose.Promise = Promise; // eh?

Thanks @Spown, I faced same deprecation warning since I put mongoose.Promise = global.Promise after importing model. Now the deprecation warning is gone.

Declaring mongoose.Promise = global.Promise in the model file as mentioned by @Spown works. This is due to node's caching of required modules. This seems fickle though. Is there not a way of ensuring that the test_helpers.js is loaded first so that I can set mongoose's promise function in this file?

Is there not a way of ensuring that...

personally I require mongoose only once in my projects, then I put it into a global Singleton object and use it everywhere for all DB purposes. Not exactly graceful, but mostly bulletproof. and I've been doing it long before the deprecation thing simply because if you use a custom connection, which I do (a connection made via mongoose.createConnection() instead of mongoose.connect()) - you have to create models from the mongoose instance linked to this connection. Otherwise it just won't work at all which is much worse than some pesky warning.

yeah I do the same as @Spown. It's certainly not ideal, but it's the only way to keep mongoose backwards compatible until the next major release when we can deprecate mpromise completely

libs/mongoose.js

import mongoose from 'mongoose'; // real mongoose only be required once here 

mongoose.Promise = global.Promise; // so that you dont have to do this on every require
const Schema = mongoose.Schema;

export {
  mongoose as default, // kind of singleton
  mongoose,
  Schema,
};

index.js

import mongoose from './libs/mongoose';
mongoose.connect(process.env.MONGODB_URI);

models/user.js

import {mongoose, Schema} from '../libs/mongoose';

export default mongoose.model('User', new Schema({
  name: String,
  password: String,
}));

@howard require() calls are cached.

So, if I understand correctly, I need to set the promise before every schema declaration instead of doing it only in one place (for example in my index file or where I'm setting the connection)
This is not a good practice, worth consider to change it to a function, something like:
mongoose.setPromise(global.Promise);

@sh-guti i think so, i had the same problem and that piece of code solve that.

At this point i don't know, if to use callbacks or promises. LOL.

Use

mongoose.createConnection(URI)

Can anyone explain, why on Earth mongoose denies the existence of native Promises and can't use them out of box?

Backwards compatibility. Mongoose 4.x was around for over a year before node 4 was released. We'll switch over with the next backwards breaking release.

When will this be?

mongoose.createConnection(URI) causes a very strange bug with Mongoose , hours of debugging with queries not working . eventually went back to

mongoose.connect(process.env.MONGODB); from mongoose.createConnection(process.env.MONGODB)

as a side note , it did stop the depreciation warning .. but stopped everything working ...

@MickL we will have an rc0 out in tbe next few weeks, follow mongoose on twitter or join the slack channel for updates

Was this page helpful?
0 / 5 - 0 ratings