MongooseError: Cast to embedded failed for value
Asked Answered
P

6

5

I'm creating a mongoose Schema but I'm getting a MongooseError.

This is my Scheme:

let RestaurantSchema = new Schema({
    ratings: {
        type: [{
            id: Number,
            value: Number,
            _id: false
        }],
        default: [
            { id: 1, value: 0 },
            { id: 2, value: 0 },
            { id: 3, value: 0 },
            { id: 4, value: 0 },
            { id: 5, value: 0 }
        ]
    },
    menu: [{
        ratings: {
            type: [{
                id: Number,
                value: Number,
                _id: false
            }],
            default: [
                { id: 1, value: 0 },
                { id: 2, value: 0 },
                { id: 3, value: 0 },
                { id: 4, value: 0 },
                { id: 5, value: 0 }
            ]
        }
    }]
})

And this is the error I'm getting:

/var/app/node_modules/mongoose/lib/schema/documentarray.js:322
             throw new CastError('embedded', valueInErrorMessage,
             ^
 MongooseError: Cast to embedded failed for value "{ id: 5, value: 0 }" at path "rating"
     at CastError (/var/app/node_modules/mongoose/lib/error/cast.js:26:11)
     at DocumentArray.cast (/var/app/node_modules/mongoose/lib/schema/documentarray.js:322:19)
     at DocumentArray.SchemaType.getDefault (/var/app/node_modules/mongoose/lib/schematype.js:616:23)
     at EmbeddedDocument.Document.$__buildDoc (/var/app/node_modules/mongoose/lib/document.js:265:22)
     at EmbeddedDocument.Document (/var/app/node_modules/mongoose/lib/document.js:61:20)
     at EmbeddedDocument [as constructor] (/var/app/node_modules/mongoose/lib/types/embedded.js:31:12)
     at new EmbeddedDocument (/var/app/node_modules/mongoose/lib/schema/documentarray.js:70:17)
     at DocumentArray.SchemaArray [as constructor] (/var/app/node_modules/mongoose/lib/schema/array.js:67:21)
     at new DocumentArray (/var/app/node_modules/mongoose/lib/schema/documentarray.js:31:13)
     at Function.Schema.interpretAsType (/var/app/node_modules/mongoose/lib/schema.js:643:16)
     at Schema.path (/var/app/node_modules/mongoose/lib/schema.js:563:29)
     at Schema.add (/var/app/node_modules/mongoose/lib/schema.js:445:12)
     at new Schema (/var/app/node_modules/mongoose/lib/schema.js:99:10)
     at Object.<anonymous> (/var/app/models/restaurant.js:12:24)
     at Module._compile (module.js:571:32)
     at Object.Module._extensions..js (module.js:580:10)
     at Module.load (module.js:488:32)
     at tryModuleLoad (module.js:447:12)
     at Function.Module._load (module.js:439:3)
     at Module.require (module.js:498:17)
     at require (internal/module.js:20:19)
     at Object.<anonymous> (/var/app/controllers/restaurant.js:6:18)
     at Module._compile (module.js:571:32)
     at Object.Module._extensions..js (module.js:580:10)
     at Module.load (module.js:488:32)
     at tryModuleLoad (module.js:447:12)
     at Function.Module._load (module.js:439:3)
     at Module.require (module.js:498:17) 

What am I doing wrong?

Protrusive answered 11/4, 2017 at 21:11 Comment(0)
I
2

It seems to be a bug in mongoose in v4.9.4. In fact there is another bug generating this one. The latter appear when you use type as an object {id: Number,value: Number,_id: false} rather than an array :

TypeError: this.__parentArray._markModified is not a function
    at EmbeddedDocument.markModified (/home/user/Desktop/node_modules/mongoose/lib/types/embedded.js:87:24)
    at SingleNested.Subdocument.markModified (/home/user/Desktop/node_modules/mongoose/lib/types/subdocument.js:62:18)
    at SingleNested.Document.$__set (/home/user/Desktop/node_modules/mongoose/lib/document.js:874:10)

This is a referenced bug referenced here. It seems to have been fixed some times but has resurfaced. I've opened a new issue about this here.

The workaround is the same as stated here, replacing in node_modules/mongoose/lib/types/embedded.js :

EmbeddedDocument.prototype.markModified = function(path) {
  this.$__.activePaths.modify(path);
  if (!this.__parentArray) {
    return;
  }

with

EmbeddedDocument.prototype.markModified = function(path) {
  this.$__.activePaths.modify(path);
  if (!this.__parentArray || !this.__parentArray._markModified) {
    return;
  }

Also, remodeling your Models into distinct Schemas helped to debug the issue :

let RatingsItemSchema = new mongoose.Schema({
    id: Number,
    value: Number,
    _id: false
});

let RatingsItem = db.model('RatingsItem', RatingsItemSchema);

let RatingsSchema = new mongoose.Schema({
    ratings: {
        type: [RatingsItemSchema],
        default: [
            { id: 1, value: 0 },
            { id: 2, value: 0 },
            { id: 3, value: 0 },
            { id: 4, value: 0 },
            { id: 5, value: 0 }
        ]
    },
    _id: false
});

let RestaurantSchema = new mongoose.Schema({
    ratings: {
        type: [RatingsItemSchema],
        default: [
            { id: 1, value: 0 },
            { id: 2, value: 0 },
            { id: 3, value: 0 },
            { id: 4, value: 0 },
            { id: 5, value: 0 }
        ]
    },
    menu: {
        type: [RatingsSchema]
    }
});

let Ratings = db.model('Ratings', RatingsSchema);
let Restaurant = db.model('Restaurant', RestaurantSchema);

let rest = new Restaurant();
rest.menu.push(new Ratings());
console.log(JSON.stringify(rest, null, 2));
Induna answered 11/4, 2017 at 22:43 Comment(1)
The workaround works but it's a little annoying have to change mongoose files. I'll wait for a new version of mongoose that maybe will solves this problem. Thank you very much.Greenlet
P
9

Not necessarily related to the situation above, but one in which this error arises (as happened to me) is when the Schema expects an object, but the code tries to save to an array. I.e., if:

var MySubSchema = new Schema(
    {
        type: String,
        meta: String
    }
)

var MySchema = new Schema(
    subSchema: MySubSchema,
    otherSubSchema: OtherSubSchema 
)

but the route/controller to save the data is as follows:

var mySchemaObj = new MySchema(
  {mySubSchema: [new MySubSchema(  //<-- Shouldn't have array "[" here
       {
          type: "foo",
          meta: "bar"
       }
    )]
  } 
)

. . . 
. . . 

mySchemaObj.save() . . . // <-- This will throw the "Cast to Embedded Failed" error, because MySchema expects a single MySubSchema Object, but the code above instantiates MySubSchema in an array. 
Pilgarlic answered 22/9, 2019 at 5:29 Comment(1)
This helps. In my case I was saving array but schema expects object :)Buddhology
N
5

This may be late but, for others who are facing the same problem as me.
Let suppose say, i have a schema something like this

const sampleSchema = new Schema({
   productId: Number
   productName: String
})

And, this is the data that I would like to store in it.

{
   productId:"product_1000",
   productName: "sampleProduct"
}

Now, when i try to store the data in it, I am gonna get the CastError: Cast to embedded failed for value.
Did you get the mistake that I did ? Let me elaborate, In the schema, the productId is an Number and the data that i am trying to store is a String. To make this work, we have to change the type of the productId from Number to String.

So, if you're receiving an cast error, check the schema once again . This is a simple mistake but cost me a good amount of time to find out the issue.

Nannie answered 11/5, 2021 at 5:28 Comment(0)
I
2

It seems to be a bug in mongoose in v4.9.4. In fact there is another bug generating this one. The latter appear when you use type as an object {id: Number,value: Number,_id: false} rather than an array :

TypeError: this.__parentArray._markModified is not a function
    at EmbeddedDocument.markModified (/home/user/Desktop/node_modules/mongoose/lib/types/embedded.js:87:24)
    at SingleNested.Subdocument.markModified (/home/user/Desktop/node_modules/mongoose/lib/types/subdocument.js:62:18)
    at SingleNested.Document.$__set (/home/user/Desktop/node_modules/mongoose/lib/document.js:874:10)

This is a referenced bug referenced here. It seems to have been fixed some times but has resurfaced. I've opened a new issue about this here.

The workaround is the same as stated here, replacing in node_modules/mongoose/lib/types/embedded.js :

EmbeddedDocument.prototype.markModified = function(path) {
  this.$__.activePaths.modify(path);
  if (!this.__parentArray) {
    return;
  }

with

EmbeddedDocument.prototype.markModified = function(path) {
  this.$__.activePaths.modify(path);
  if (!this.__parentArray || !this.__parentArray._markModified) {
    return;
  }

Also, remodeling your Models into distinct Schemas helped to debug the issue :

let RatingsItemSchema = new mongoose.Schema({
    id: Number,
    value: Number,
    _id: false
});

let RatingsItem = db.model('RatingsItem', RatingsItemSchema);

let RatingsSchema = new mongoose.Schema({
    ratings: {
        type: [RatingsItemSchema],
        default: [
            { id: 1, value: 0 },
            { id: 2, value: 0 },
            { id: 3, value: 0 },
            { id: 4, value: 0 },
            { id: 5, value: 0 }
        ]
    },
    _id: false
});

let RestaurantSchema = new mongoose.Schema({
    ratings: {
        type: [RatingsItemSchema],
        default: [
            { id: 1, value: 0 },
            { id: 2, value: 0 },
            { id: 3, value: 0 },
            { id: 4, value: 0 },
            { id: 5, value: 0 }
        ]
    },
    menu: {
        type: [RatingsSchema]
    }
});

let Ratings = db.model('Ratings', RatingsSchema);
let Restaurant = db.model('Restaurant', RestaurantSchema);

let rest = new Restaurant();
rest.menu.push(new Ratings());
console.log(JSON.stringify(rest, null, 2));
Induna answered 11/4, 2017 at 22:43 Comment(1)
The workaround works but it's a little annoying have to change mongoose files. I'll wait for a new version of mongoose that maybe will solves this problem. Thank you very much.Greenlet
D
1

In my case the req.body did not match the pre defined mongoose schema, I was trying to save an array of ObjectId, The req.body was:

{
   cart: ["60d9b457a6c11f2a3818051a"]
}

But the mongoose schema was

cart: [
   {
      product: {
         type: mongoose.Schema.Types.ObjectId,
         ref: 'products'
      }
   }
]

I changed that mongoose schema like this 👇 to make it work:

cart: [
   {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'products'
   }
]
Dowager answered 5/7, 2021 at 6:25 Comment(0)
P
1

Just if anyone else has this same problem as me: I had this issue when I was setting my object _id with uuidv4() in my react project, so when my API received this object with this _id containing a long v4() string, it was making my mongoose throw this exception when it tried to persist the object:

(part of the exception)

  path: 'middleComponents',
  reason: CastError: Cast to ObjectId failed for value "f41b7983-09b8-4463-bf5b-e59a8f7a19f6" (type string) at path "_id"
      at ObjectId.cast (E:\path-to-project\node_modules\mongoose\lib\schema\objectid.js:248:11)
      at ObjectId.SchemaType.applySetters (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1123:12)
      at EmbeddedDocument.$set (E:\path-to-project\node_modules\mongoose\lib\document.js:1309:20)
      at EmbeddedDocument.$set (E:\path-to-project\node_modules\mongoose\lib\document.js:1058:16)
      at EmbeddedDocument.Document (E:\path-to-project\node_modules\mongoose\lib\document.js:148:12)
      at EmbeddedDocument [as constructor] (E:\path-to-project\node_modules\mongoose\lib\types\embedded.js:47:12)
      at new EmbeddedDocument (E:\path-to-project\node_modules\mongoose\lib\schema\documentarray.js:116:17)
      at DocumentArrayPath.cast (E:\path-to-project\node_modules\mongoose\lib\schema\documentarray.js:462:22)
      at DocumentArrayPath.SchemaType.applySetters (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1123:12)
      at DocumentArrayPath.SchemaType._castForQuery (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1601:15)
      at DocumentArrayPath.SchemaType.castForQueryWrapper (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1563:22)
      at castUpdateVal (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:546:19)
      at walkUpdatePath (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:366:24)
      at castUpdate (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:96:7)
      at model.Query._castUpdate (E:\path-to-project\node_modules\mongoose\lib\query.js:4721:10)
      at castDoc (E:\path-to-project\node_modules\mongoose\lib\query.js:4751:18) {
    stringValue: '"f41b7983-09b8-4463-bf5b-e59a8f7a19f6"',
    messageFormat: undefined,
    kind: 'ObjectId',
    value: 'f41b7983-09b8-4463-bf5b-e59a8f7a19f6',
    path: '_id',
    reason: Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
        at new ObjectID (E:\path-to-project\node_modules\bson\lib\bson\objectid.js:59:11)
        at castObjectId (E:\path-to-project\node_modules\mongoose\lib\cast\objectid.js:25:12)
        at ObjectId.cast (E:\path-to-project\node_modules\mongoose\lib\schema\objectid.js:246:12)
        at ObjectId.SchemaType.applySetters (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1123:12)
        at EmbeddedDocument.$set (E:\path-to-project\node_modules\mongoose\lib\document.js:1309:20)
        at EmbeddedDocument.$set (E:\path-to-project\node_modules\mongoose\lib\document.js:1058:16)
        at EmbeddedDocument.Document (E:\path-to-project\node_modules\mongoose\lib\document.js:148:12)
        at EmbeddedDocument [as constructor] (E:\path-to-project\node_modules\mongoose\lib\types\embedded.js:47:12)
        at new EmbeddedDocument (E:\path-to-project\node_modules\mongoose\lib\schema\documentarray.js:116:17)
        at DocumentArrayPath.cast (E:\path-to-project\node_modules\mongoose\lib\schema\documentarray.js:462:22)
        at DocumentArrayPath.SchemaType.applySetters (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1123:12)
        at DocumentArrayPath.SchemaType._castForQuery (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1601:15)
        at DocumentArrayPath.SchemaType.castForQueryWrapper (E:\path-to-project\node_modules\mongoose\lib\schematype.js:1563:22)
        at castUpdateVal (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:546:19)
        at walkUpdatePath (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:366:24)
        at castUpdate (E:\path-to-project\node_modules\mongoose\lib\helpers\query\castUpdate.js:96:7),
    valueType: 'string'
  },
  valueType: 'string'
Preoccupy answered 15/3, 2022 at 3:32 Comment(0)
S
0

For someone who can't solve the issue check if you update your data with object contained stringified field:

    return await Realty.findByIdAndUpdate(
        id,
        {
            ...realty,
            $push: { images: { $each: images } },
        },
        { new: true },
    );

images was absolutely valid JSON but for realty.images it was a stringified JSON and this is not work for mongoose: it seems like before replace it checks realty fields for validity.

Speller answered 28/2 at 13:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.