question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cast to ObjectId failed for value \"aggregate\" at path \"_id\" for model Payment\"

See original GitHub issue

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

What is the current behavior? Cast to ObjectId failed for value emitting

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

What is the expected behavior? It should accept the ref key as String

Please mention your node.js, mongoose and MongoDB version. NODE: 10.0.0, “mongoose”: “^5.0.0-rc0” v4.0.0

let mongoose = require("mongoose");
let Schema = mongoose.Schema;
let ObjectId = Schema.ObjectId;

let modelSchema = new Schema(
  {
    userId: {type: ObjectId},
    name: { type: String },
    amount: {
        type: Number
    },
    categoryId: {
        type: String,
        ref: 'Category'
    },
    cardId: {
      type: String,
      ref: 'Card'
    },
    paymentDate: {
      type: Date,
      default: new Date
    }
  },
  {
    timestamps: {}
  }
);



let modelObj = mongoose.model("Payment", modelSchema);
module.exports = modelObj;

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6

github_iconTop GitHub Comments

4reactions
lineuscommented, Aug 18, 2018

@techyaura you can create a virtual on paymentSchema that defines specific local/foreign keys.

Here is the example from earlier updated with virtuals instead:

6879.js

#!/usr/bin/env node
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
const conn = mongoose.connection;
const Schema = mongoose.Schema;

let paymentSchema = new Schema(
  {
    userId: { type: Schema.Types.ObjectId },
    name: { type: String },
    amount: {
      type: Number
    },
    categoryId: String,
    cardId: String,
    paymentDate: {
      type: Date,
      default: new Date
    }
  },
  {
    timestamps: {}
  }
);

paymentSchema.virtual('card', {
  ref: 'Card',
  localField: 'cardId',
  foreignField: 'slug',
  justOne: true
});

paymentSchema.virtual('category', {
  ref: 'Category',
  localField: 'categoryId',
  foreignField: 'slug',
  justOne: true
});

const cardSchema = new Schema(
  {
    userId: { type: Schema.Types.ObjectId },
    name: { type: String, unique: true },
    slug: { type: String, unique: true },
    isSystemDefined: {
      type: Boolean,
      default: false
    },
    status: {
      type: Boolean,
      default: false
    },
    isDeleted: {
      type: Boolean,
      default: false
    }
  },
  {
    timestamps: {}
  }
);

const categorySchema = new Schema(
  {
    userId: {
      type: Schema.Types.ObjectId
    },
    name: { type: String, unique: true },
    slug: { type: String, unique: true },
    status: {
      type: Boolean,
      default: false
    },
    isDeleted: {
      type: Boolean,
      default: false
    },
    isSystemDefined: {
      type: Boolean,
      default: false
    }
  },
  {
    timestamps: {}
  }
);

categorySchema.set('toObject', { virtuals: true });
categorySchema.set('toJSON', { virtuals: true });

const Category = mongoose.model('Category', categorySchema);
const Card = mongoose.model('Card', cardSchema);
const Payment = mongoose.model('Payment', paymentSchema);

const uid = new mongoose.Types.ObjectId();

const category = new Category({
  userId: uid,
  name: 'billy',
  slug: 'bugsAreCool'
});

const card = new Card({
  userId: uid,
  name: 'MyCard',
  slug: 'getTheSalt'
});

const payment = new Payment({
  userId: uid,
  name: 'salt',
  amount: 100,
  categoryId: category.slug,
  cardId: card.slug
});

async function run() {
  await conn.dropDatabase();
  await category.save();
  await card.save();
  await payment.save();
  let doc = await Payment.findOne({}).populate('card category');
  assert.strictEqual(doc.category.name, 'billy');
  assert.strictEqual(doc.card.name, 'MyCard');
  console.log('All assertions PASSED!');
  return conn.close();
}

run();

Output:

issues: ./6879.js
All assertions PASSED!
issues:
1reaction
lineuscommented, Aug 18, 2018

@techyaura I’m assuming you are calling something like Payment.findOne().populate('categoryId').

Mongoose is going to use the Model pointed to by the value of ref and the _id field of the docs in the corresponding collection to match the value of the path in the document being populated.

Your _id fields from the ‘Card’ and ‘Category’ schema are using the default of ObjectId. A string like ‘aggregate’ is never going to successfully be cast as an ObjectId.

You need to store the _id of the Card or Category document in that field. If you store the _id of the foreign doc, it is fine to use String as the type.

Here’s a complete repro script based on your schema:

6879.js

#!/usr/bin/env node
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
const conn = mongoose.connection;
const Schema = mongoose.Schema;

let paymentSchema = new Schema(
  {
    userId: { type: Schema.Types.ObjectId },
    name: { type: String },
    amount: {
      type: Number
    },
    categoryId: {
      type: String,
      ref: 'Category'
    },
    cardId: {
      type: String,
      ref: 'Card'
    },
    paymentDate: {
      type: Date,
      default: new Date
    }
  },
  {
    timestamps: {}
  }
);

const cardSchema = new Schema(
  {
    userId: { type: Schema.Types.ObjectId },
    name: { type: String, unique: true },
    slug: { type: String, unique: true },
    isSystemDefined: {
      type: Boolean,
      default: false
    },
    status: {
      type: Boolean,
      default: false
    },
    isDeleted: {
      type: Boolean,
      default: false
    }
  },
  {
    timestamps: {}
  }
);

const categorySchema = new Schema(
  {
    userId: {
      type: Schema.Types.ObjectId
    },
    name: { type: String, unique: true },
    slug: { type: String, unique: true },
    status: {
      type: Boolean,
      default: false
    },
    isDeleted: {
      type: Boolean,
      default: false
    },
    isSystemDefined: {
      type: Boolean,
      default: false
    }
  },
  {
    timestamps: {}
  }
);

categorySchema.set('toObject', { virtuals: true });
categorySchema.set('toJSON', { virtuals: true });

const Category = mongoose.model('Category', categorySchema);
const Card = mongoose.model('Card', cardSchema);
const Payment = mongoose.model('Payment', paymentSchema);

const uid = new mongoose.Types.ObjectId();

const category = new Category({
  userId: uid,
  name: 'billy',
  slug: 'bugsAreCool'
});

const card = new Card({
  userId: uid,
  name: 'MyCard',
  slug: 'getTheSalt'
});

const payment = new Payment({
  userId: uid,
  name: 'salt',
  amount: 100,
  categoryId: category.id,
  cardId: card.id
});

async function run() {
  await conn.dropDatabase();
  await category.save();
  await card.save();
  await payment.save();
  let doc = await Payment.findOne({}).populate('cardId categoryId');
  assert.strictEqual(doc.categoryId.name, 'billy');
  assert.strictEqual(doc.cardId.name, 'MyCard');
  console.log('All assertions PASSED!');
  return conn.close();
}

run();

Output:

issues: ./6879.js
All assertions PASSED!
issues:
Read more comments on GitHub >

github_iconTop Results From Across the Web

Mongoose: CastError: Cast to ObjectId failed for value "[object ...
Short answer: use mongoose.Types.ObjectId. Mongoose (but not mongo) can accept object Ids as strings and "cast" them properly for you, so just use:...
Read more >
cast to objectid failed for value "" (type string) at path "_id" for ...
Mongoose's findById method casts the id parameter to the type of the model's _id field so that it can properly query for the...
Read more >
[SOLVED] CastError: Cast to ObjectId failed for value "{ articleId
When I click My Article button from the homepage I get the following error : CastError: Cast to ObjectId failed for value “{...
Read more >
Mongoose v6.8.2: API docs
isValidObjectId (); Mongoose.prototype.model(); Mongoose.prototype. ... path «String» The path a.b.c in the doc where this cast error occurred.
Read more >
Cast to ObjectId failed for value - Code Grepper
// it happens when you pass an invalid id to mongoose. 2. // so first check it before proceeding, using mongoose isValid function....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found