Mongoose: ValidationError when using array in Schema

Created on 8 Aug 2019  路  13Comments  路  Source: Automattic/mongoose

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

What is the current behavior?
After defining my schema similar to the following one:

const UserSchema = new mongoose.Schema({
  roles: {
    type: [String],
    index: true,
  },
});

mongoose.model('User', UserSchema)

If I try to instantiate a new User like this:

const user = new User({ roles: ['super-admin'] });

It raises the following exception ValidationError: User validation failed: roles: Cast to Array failed for value "[ 'super-admin' ]" at path "roles"

Instantiating the user with an empty roles array does not raise any exception.
This is happening on [email protected], downgrading to 5.6.8 fixes it.

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

The schema shown above should be enough to reproduce the issue.

What is the expected behavior?
No ValidationError exception raised when instantiating a model with an array in the schema.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
node 10.16.0
mongoose 5.6.9
mongo 4.0.4

interop issue

Most helpful comment

@vkarpov15 I have put together a small reproduction repository: https://github.com/BrunoGodefroy/repro-mongoose-issue-8053

I tried to simplify it at a maximum to showcase the error, I could not remove jest while keeping the bug so it might be caused by babel transpiling the code for jest.

Hope that helps

All 13 comments

The below script executes without any error for me, please modify the below script to demonstrate your issue.

const assert = require('assert');
const mongoose = require('mongoose');

const GITHUB_ISSUE = `gh8053`;
const connectionString = `mongodb://localhost:27017/${ GITHUB_ISSUE }`;
const { Schema } = mongoose;

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  await mongoose.connect(connectionString, { useNewUrlParser: true });
  await mongoose.connection.dropDatabase();

  console.log(mongoose.version);

  const UserSchema = new mongoose.Schema({
    roles: {
      type: [String],
      index: true,
    },
  });

  const User = mongoose.model('User', UserSchema);

  const user = new User({ roles: ['super-admin'] });

  await user.save();
}

Output:

$ node gh-8053.js 
5.6.9
(node:25883) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
done

@vkarpov15 I have put together a small reproduction repository: https://github.com/BrunoGodefroy/repro-mongoose-issue-8053

I tried to simplify it at a maximum to showcase the error, I could not remove jest while keeping the bug so it might be caused by babel transpiling the code for jest.

Hope that helps

I also have this error when testing an application using mongoose schemas with arrays with jest.
Error does not occur in mongoose 5.6.7.

I also have this error, and also with a string array. It appeared without any changes in that code for quite some time. The only difference was that I upgraded Mongoose to 5.6.9.
When I downgrade(d) to 5.6.8, the problem disappears again.

This appears to be yet another bug with Jest. Not to harp about this too much, but Jest is horribly broken and you should really use Mocha or some other framework that doesn't invent its own JavaScript runtime that isn't quite Node.js or a browser. Because Jest makes up its own runtime by monkeypatching everything, code that works fine in Node.js may not work in Jest and vice versa, so Jest is not a reliable way to test Node.js projects.

It looks like this issue comes down to Jest stubbing out require(), so if you require('./) in a directory where the parent dir happens to have a file with the same name as the current directory, Jest's require() gives you the parent dir's file. For example, suppose you have the below file structure:

- test.js
- dir.js
- dir
  - index.js
  - fn.js

test.js

const fn = require('./dir/fn');

it('test', function() {
  console.log(fn());
});

dir.js

module.exports = 'top-level';

dir/index.js

module.exports = 'nested';

dir/fn.js

module.exports = function() {
  return require('./');
};

Running test.js will output:


As opposed to nested like in Node.js.

Can anyone link to the relevant jest bug? It'd be good to track so that we know when we can upgrade mongoose to v5.6.9 or later.

This bug has eaten up my brain today.. I'm placing orders with Postman and axios and it succeeds with the data, but fails in jest with Mongoose at 5.6.9

My test:

describe('Test the /orders/place path', () => {
    test('It should respond with 200 and oid', (done) => {
        request(app).post('/v1/orders/place')
            .send({
                key1,
                key2: true,
                key3: false,
                key4: {},
                key5: false,
                key6: ["sometext", "sometext"],
                key7: ['process it faster'],
                key8: {
                    startTime: newDate,
                    endTime: newDate.setHours(newDate.getHours() + 4),
                },
            })
            .set('Accept', 'application/json')
            .set('Authorization', someJWT)
            .expect('Content-Type', /json/)
            .then((response) => {
                expect(response.statusCode).toBe(200);
                expect(response.body.success).toBe(true);
                expect(typeof response.body.oid).toBe('number');
                orderID = response.body.oid;
                done();
            });
    });
});

key6 and key7 are breaking with the following error:

key7: MongooseError {
            message: 'Cast to Array failed for value "process it faster" at path "key7"',
            name: 'CastError',
            stringValue: '"process it faster"',
            kind: 'Array',
            value: 'process it faster',
            path: 'key7',
            reason: [MongooseError]
          }

^^ similarly for key6

The Mongoose model is:

...,
    key6: {
        type: [String],
    },
    ke7: {
        type: [String],
    },
...

Can someone please tell me what's wrong? Cause I don't have a clue!

@saifali96 it's a bug in Jest. See this comment. I strongly recommend moving off of Jest. Jest is an anti-pattern because it does so much monkeypatching that it creates a distinct JavaScript environment that isn't quite Node.js or a browser. Code that works in Jest may not work in Node.js and vice versa.

@esetnik we'll work around this bug and similar bugs in the Mongoose code. But I strongly recommend you move off of Jest for the reasons stated above. If you're using Jest, you're not actually testing your code, you're testing how your code runs in Jest, which doesn't necessarily line up with how your code runs without Jest.

I don鈥檛 think it鈥檚 necessary for mongoose to work around bugs in Jest. You鈥檝e made it clear that Jest is not a supported test runner. I was just wondering if anyone reported this yet so that Jest can fix it. Surely if this is a bug in Jest then mongoose isn鈥檛 the only library having issues. It seems like the reproduction steps were clear enough that this could be easily reproed.

I haven't reported an issue yet, but I will in the next few days. You're welcome to open up an issue in the Jest repo in the meantime.

I had the same problem - I updated mongoose to 5.6.11 and it fixes it.

Thanks @vkarpov15 ! I fixed it by looking at your comment. Also thanks for releasing the patch.

I opened up an issue with Jest :point_up:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Igorpollo picture Igorpollo  路  3Comments

ghost picture ghost  路  3Comments

jeneser picture jeneser  路  3Comments

simonxca picture simonxca  路  3Comments

adamreisnz picture adamreisnz  路  3Comments