Local Library Tutorial Genre List Detail Page BSON Type Error

Following the MDN Web Docs server side Local Library Tutorial, for the Genre Detail Page, (Genre Detail Page, the tutorial mentions a mongoose error coming from the req.params.id.

The tutorial recommends that we use mongoose.Types.ObjectId() to convert the id to a type that can be used. I implemented the mongoose.Types.ObjectId() code, but am now getting a different error: “BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer”.

Does anyone know the fix for the BSON Type Error?

Johnson

Using the following dependencies:

node v16.17.0
"async": "^3.2.4",
"express": "^4.16.1",
"mongoose": "^6.5.3",

This is what I have in my genreController.js:

const Genre = require('../models/genre');
const Book = require('../models/book');
const mongoose = require('mongoose');
const async = require('async');
........................
// Display detail page for a specific Genre.
exports.genre_detail = (req, res, next) => {
  const id = mongoose.Types.ObjectId(req.params.id);
  async.parallel(
    {
      genre(callback) {
        Genre.findById(id).exec(callback);
      },

      genre_books(callback) {
        Book.find({ genre: id }).exec(callback);
      },
    },
    (err, results) => {
      if (err) {
        return next(err);
      }
      if (results.genre == null) {
        // No results.
        const err = new Error('Genre not found');
        err.status = 404;
        return next(err);
      }
      // Successful, so render
      res.render('genre_detail', {
        title: 'Genre Detail',
        genre: results.genre,
        genre_books: results.genre_books,
      });
    }
  );
};

This is what I have in my genre.js:

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

const GenreSchema = new Schema({
  name: { type: String, required: true, minLength: 3, maxLength: 100 },
});

// Virtual for genre's URL
GenreSchema.virtual('url').get(() => {
  return `/catalog/genre/` + this._id;
});

//Export model & Compile model from schema
module.exports = mongoose.model('Genre', GenreSchema);

** And here are my routes for genre:

// GET request for one Genre.
router.get('/genre/:id', genre_controller.genre_detail);

// GET request for list of all Genre.
router.get('/genres', genre_controller.genre_list);

Hi @johnson.elugbadebo

I don’t have any experience with the used technologies but I would output the content of req.params.id when the error occurs. For whatever reason the cast fails because the id doesn’t have one of the forms listed in the error message. Maybe there’s a space at the start or end or the value is undefined.

I hope that helps you in finding the error. I’m sorry I can’t just point to the problem.

Michael

Hi @mikoMK,

Thanks for following up on this, much appreciated. I have literally just now finally resolved the issue. So, to declare the “Virtual” property in the Mongoose Schema, apparently you have to use the notation as explicitly laid out in the Mongoose docs.

I was using arrow function notation (which I generally prefer when writing JavaScript) as in the following:

/* Virtual for this genre instance URL. */
GenreSchema
.virtual('url')
.get( () => {
  return '/catalog/genre/'+this._id;
});

The Mongoose docs use the following notation, where “function” is spelled out:

/* Virtual for this genre instance URL. */
GenreSchema
.virtual('url')
.get(function () {
  return '/catalog/genre/'+this._id;
});

Apparently, the code doesn’t work with arrow notation. Lesson learned.

Thanks again for following up.

Johnson

1 Like

I’m glad you could solve your problem and thanks for sharing the solution. This will certainly help others. :smiling_face_with_three_hearts:

The reason it’s working with a traditional function but not with an arrow function is a tricky little property of arrow functions. They don’t bind “this”. Therefore “this” won’t be the GenreSchema inside the arrow function and _id can’t be found.

I encountered a similar situations while programming with Vue.js. There are specific situations where you can’t use arrow functions for the exact same reason.

I am finally done with the MDN Web Docs tutorials. I deployed my site through Heroku, it was great to see all that work pay off in an app deployment.

Regarding the arrow functions and “this”, I would add a note in the appropriate places on the MDN Web Docs tutorials spelling out the issue – it might save someone in the future a weeks worth of heartache. Despite my love for the efficiency of arrow function syntax, I have resorted to just using “function” throughout my code. It makes it easier to do “ctrl + f”, quickly understand what’s what, etc.

I’m glad to here that!

You could raise an issue on the MDN GitHub repo: https://github.com/mdn/content/issues

1 Like