Sling Academy
Home/Node.js/How to Specify a Custom Error Message in Mongoose

How to Specify a Custom Error Message in Mongoose

Last updated: December 30, 2023

Introduction

Mongoose is a powerful ODM library for MongoDB, which provides built-in validation features. However, the default error messages may not always be descriptive enough. Customizing these messages can greatly enhance the experience for end users and developers.

Learning to specify custom error messages in Mongoose can lead to more maintainable and user-friendly validation. This tutorial will guide you through different methods for setting up your error messages in Mongoose schemas.

Custom Error Message in Basic Validation

Start by defining a simple schema. Mongoose allows you to specify validation rules along with custom error messages in the schema definition:

const mongoose = require('mongoose');
const { Schema } = mongoose;

const userSchema = new Schema({
  username: {
    type: String,
    required: [true, 'Username is required. Oops.'s] // Custom error message for the required validator
  }
});

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

Using Validate Method

The validate method allows more complex validations:

userSchema.path('email').validate({
  validator: function(value) {
    return /\S+@\S+\.\S+/.test(value);
  },
  message: props => `${props.value} is not a valid email address!` // Custom error message using ES6 template strings
});

Custom Error Message in Advanced Validation

For asynchronous validation, use a function that returns a promise. This is useful when your validation involves asynchronous operations, like checking uniqueness against a database:

userSchema.path('username').validate({
  validator: function(value) {
    return User.findOne({ username: value }).then(user => {
      return !user;
    });
  },
  message: 'Username is already taken.' // Custom error message
});

Custom Validators

Create custom validator functions for scenarios not covered by Mongoose’s built-in validators:

function arrayLimit(val) {
  return val.length <= 3;
}

userSchema.path('tags').validate({
  validator: arrayLimit,
  message: 'You can specify up to 3 tags.' // Custom error message
});

Error Handling

After defining the schema validations, you should know how to handle errors. Use try-catch blocks to catch validation errors:

const newUser = new User({ username: 'jdoe', email: 'invalid-email' });
try {
  await newUser.save();
} catch (error) {
  if (error.name === 'ValidationError') {
    for (field in error.errors) {
      console.error(error.errors[field].message); // Log or handle custom error messages
    }
  }
}

Using Middleware

For an advanced setup, Mongoose middleware can help you intercept and modify errors before they reach the application layer:

userSchema.post('save', function(error, doc, next) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('There is a duplicate key error.'));
  } else {
    next(error);
  }
});

Conclusion

Custom error messages are an essential feature of application development. Whether through schema definitions or middleware, Mongoose provides a flexible approach to enrich error handling. This leads to improved debugging, better user guidance, and a cleaner codebase.

Next Article: Using the Mongoose Model.find() function (with examples)

Previous Article: Virtuals in Mongoose: Explained with Examples

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates