Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document.populate() throws an error when populating an array of immutable items #10159

Closed
ThoseGrapefruits opened this issue Apr 19, 2021 · 4 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue
Milestone

Comments

@ThoseGrapefruits
Copy link

Do you want to request a feature or report a bug?

Report a bug.

What is the current behavior?

When calling document.populate() with a path to an array whose elements are marked as immutable, Mongoose throws the following error:

/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/schema/array.js:392
        throw new CastError('[' + e.kind + ']', util.inspect(value), this.path + '.' + i, e, this);
              ^

CastError: Cast to [undefined] failed for value "["607dec18c3b1d8443014f1dc"]" at path "friends.0"
    at SchemaArray.cast (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/schema/array.js:392:15)
    at convertTo_id (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js:515:28)
    at getModelsMapForPopulate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js:242:13)
    at populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4364:21)
    at _populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4335:5)
    at /Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4312:5
    at promiseOrCallback (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/promiseOrCallback.js:9:12)
    at Mongoose._promiseOrCallback (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/index.js:1154:10)
    at Function.Model.populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4310:23)
    at model.populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/document.js:3917:19)
    at /Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/document.js:3989:10
    at /Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:5
    at new Promise (<anonymous>)
    at promiseOrCallback (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/promiseOrCallback.js:30:10)
    at model.Document.execPopulate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/document.js:3988:10)
    at file:///Users/thosegrapefruits/Desktop/populate-immutable-array.mjs:23:33 {
  stringValue: '"["607dec18c3b1d8443014f1dc"]"',
  messageFormat: undefined,
  kind: '[undefined]',
  value: '["607dec18c3b1d8443014f1dc"]',
  path: 'friends.0',
  reason: TypeError: Invalid `path`. Must be either string or array
      at Object.exports.get (/Users/thosegrapefruits/Desktop/node_modules/mpath/lib/index.js:59:11)
      at Object.exports.getValue (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/utils.js:596:16)
      at model.Document.$__getValue (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/document.js:1558:16)
      at model.immutableSetter (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/schematype/handleImmutable.js:37:25)
      at ObjectId.SchemaType._applySetters (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/schematype.js:1075:16)
      at ObjectId.SchemaType.applySetters (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/schematype.js:1099:16)
      at SchemaArray.cast (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/schema/array.js:388:29)
      at convertTo_id (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js:515:28)
      at getModelsMapForPopulate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js:242:13)
      at populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4364:21)
      at _populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4335:5)
      at /Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4312:5
      at promiseOrCallback (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/helpers/promiseOrCallback.js:9:12)
      at Mongoose._promiseOrCallback (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/index.js:1154:10)
      at Function.Model.populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/model.js:4310:23)
      at model.populate (/Users/thosegrapefruits/Desktop/node_modules/mongoose/lib/document.js:3917:19)
}

If the current behavior is a bug, please provide the steps to reproduce.

Repro script. Using module syntax, save in something.mjs and it should run fine w/ node.

import mongoose from 'mongoose';

mongoose.connect('mongodb://localhost:27017/cats', {
  useNewUrlParser: true, useUnifiedTopology: true
});

const Cat = mongoose.model('Cat', {
  name: String, 

  friends: [ {
    immutable: true,
    type: mongoose.ObjectId,
    ref: 'Cat'
  } ]

  // Note that the following works fine, but the per-array-item immutability is
  // still desired because otherwise you can do cat.friends[0] = someOtherCatId

  // friends: {
  //   immutable: true,
  //   type: [ {
  //     type: mongoose.ObjectId,
  //     ref: 'Cat'
  //   } ],
  // }
});

const friend = new Cat({ name: 'Zildjian' });
await friend.save();

const myCat = new Cat({ name: 'Lord Fluffles', friends: [ friend.id ] })
await myCat.save();

await myCat.populate('friends').execPopulate();

What is the expected behavior?

The field's array elements should be populated, and no error should be thrown.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.

Node: 15.14.0
Mongoose: 5.12.5 (but it seems to have broken in 5.11.10, as 5.11.9 is the last version where this worked fine)
MongoDB: 4.2.11

@IslandRhythms
Copy link
Collaborator

Not the same error but it is giving an error:

const mongoose = require('mongoose');

const Cat = mongoose.model('Cat', {
    name: String,
    friends: [{
        immutable: true,
        type: mongoose.isValidObjectId,
        ref: 'Cat'
    }]
});

async function run() {
    await mongoose.connect('mongodb://localhost:27017/test', {
        useNewUrlParser: true,
        useUnifiedTopology: true
      });
    
    await mongoose.connection.dropDatabase();

    const friend = new Cat({name: 'Zildjian'});
    await friend.save();
    const myCat = new Cat({name: 'Lord FLuffles', friends: [friend.id]});
    await myCat.save();
    await myCat.populate('friends').execPopulate();
}

run();

@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Apr 21, 2021
@ThoseGrapefruits
Copy link
Author

Oh, I think in your script, the line

type: mongoose.isValidObjectId

should be

type: mongoose.Types.ObjectId

With that, it throws what looks to be the same error as mine.

@IslandRhythms
Copy link
Collaborator

Yup. that was it. Thank you.

@vkarpov15 vkarpov15 added this to the 5.12.8 milestone Apr 27, 2021
vkarpov15 added a commit that referenced this issue May 8, 2021
@ThoseGrapefruits
Copy link
Author

Thanks for the quick turnaround @vkarpov15 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue
Projects
None yet
Development

No branches or pull requests

3 participants