When reviewing a PR last week, I came to know that ObjectId.isValid is not really good to validate an ObjectId from my colleague. ObjectId.isValid will return true for validating a string of 12 characters in length. Why I’m concerned about this issue? Because if we input any string as _id to Mongodb’s Find API for example, it’ll throw an error and possibly crash the process if not handled correctly.

As far as I know, this ObjectId.isValid behavior is for NodeJS Mongo Driver, I don’t know if it happens in another language or library.

const mongodb = require("mongodb");
const ObjectId = mongodb.ObjectId;

const string12char = "aaabbbcccddd";

const string24char = "aaaaaabbbbbbccccccdddddd";

const string24notHex = "zzzzzzzzzzzzzzzzzzzzzzzz";

const validObjectId = "635ca5688ac8cd015b0bc6ee";

console.log("ObjectId.isValid string12char: ", ObjectId.isValid(string12char)); // true

console.log("ObjectId.isValid string24char: ", ObjectId.isValid(string24char)); // true

console.log("ObjectId.isValid string24notHex: ", ObjectId.isValid(string24notHex)); // false

console.log("ObjectId.isValid validObjectId: ", ObjectId.isValid(validObjectId)); // true

Validating with Regex

As mentioned in this issue from Mongoose, it is better to use regex to validate an ObjectId.

const mongodb = require("mongodb");
const ObjectId = mongodb.ObjectId;

const string12char = "aaabbbcccddd";

const string24char = "aaaaaabbbbbbccccccdddddd";

const string24notHex = "zzzzzzzzzzzzzzzzzzzzzzzz";

const validObjectId = "635ca5688ac8cd015b0bc6ee";

const validateWithRegex = (value) => {
  const regex = new RegExp(/^[a-fA-F0-9]{24}$/);

  if (value !== "" && typeof value === "string") {
    const result = value.match(regex);
    return result?.length > 0;
  }
  return false;
};

console.log("validateWithRegex string12char: ", validateWithRegex(string12char)); // false

console.log("validateWithRegex string24char: ", validateWithRegex(string24char)); // true

console.log("validateWithRegex string24notHex: ", validateWithRegex(string24notHex)); // false

console.log("validateWithRegex validObjectId: ", validateWithRegex(validObjectId)); // true