Mongoose обработка ошибок

  • Error()
  • Error.CastError
  • Error.DivergentArrayError
  • Error.DocumentNotFoundError
  • Error.MissingSchemaError
  • Error.MongooseServerSelectionError
  • Error.OverwriteModelError
  • Error.ParallelSaveError
  • Error.StrictModeError
  • Error.StrictPopulateError
  • Error.ValidationError
  • Error.ValidatorError
  • Error.VersionError
  • Error.messages
  • Error.prototype.name

Error()

Parameters:
  • msg
    «String» Error message
Type:
  • «constructor»
Inherits:
  • «Error»

MongooseError constructor. MongooseError is the base class for all
Mongoose-specific errors.

Example:

const Model = mongoose.model('Test', new mongoose.Schema({ answer: Number }));
const doc = new Model({ answer: 'not a number' });
const err = doc.validateSync();

err instanceof mongoose.Error.ValidationError; // true


Error.CastError

Type:
  • «property»

An instance of this error class will be returned when mongoose failed to
cast a value.


Error.DivergentArrayError

Type:
  • «property»

An instance of this error will be returned if you used an array projection
and then modified the array in an unsafe way.


Error.DocumentNotFoundError

Type:
  • «property»

An instance of this error class will be returned when save() fails
because the underlying
document was not found. The constructor takes one parameter, the
conditions that mongoose passed to updateOne() when trying to update
the document.


Error.MissingSchemaError

Type:
  • «property»

Thrown when you try to access a model that has not been registered yet


Error.MongooseServerSelectionError

Type:
  • «property»

Thrown when the MongoDB Node driver can’t connect to a valid server
to send an operation to.


Error.OverwriteModelError

Type:
  • «property»

Error.ParallelSaveError

Type:
  • «property»

An instance of this error class will be returned when you call save() multiple
times on the same document in parallel. See the FAQ for more
information.


Error.StrictModeError

Type:
  • «property»

Thrown when your try to pass values to model constructor that
were not specified in schema or change immutable properties when
strict mode is "throw"


Error.StrictPopulateError

Type:
  • «property»

An instance of this error class will be returned when mongoose failed to
populate with a path that is not existing.


Error.ValidationError

Type:
  • «property»

An instance of this error class will be returned when validation failed.
The errors property contains an object whose keys are the paths that failed and whose values are
instances of CastError or ValidationError.


Error.ValidatorError

Type:
  • «property»

A ValidationError has a hash of errors that contain individual
ValidatorError instances.

Example:

const schema = Schema({ name: { type: String, required: true } });
const Model = mongoose.model('Test', schema);
const doc = new Model({});

// Top-level error is a ValidationError, **not** a ValidatorError
const err = doc.validateSync();
err instanceof mongoose.Error.ValidationError; // true

// A ValidationError `err` has 0 or more ValidatorErrors keyed by the
// path in the `err.errors` property.
err.errors['name'] instanceof mongoose.Error.ValidatorError;

err.errors['name'].kind; // 'required'
err.errors['name'].path; // 'name'
err.errors['name'].value; // undefined

Instances of ValidatorError have the following properties:

  • kind: The validator’s type, like 'required' or 'regexp'
  • path: The path that failed validation
  • value: The value that failed validation

Error.VersionError

Type:
  • «property»

An instance of this error class will be returned when you call save() after
the document in the database was changed in a potentially unsafe way. See
the versionKey option for more information.


Error.messages

Type:
  • «property»
See:
  • Error.messages

The default built-in validator error messages.


Error.prototype.name

Type:
  • «String»

The name of the error. The name uniquely identifies this Mongoose error. The
possible values are:

  • MongooseError: general Mongoose error
  • CastError: Mongoose could not convert a value to the type defined in the schema path. May be in a ValidationError class’ errors property.
  • DivergentArrayError: You attempted to save() an array that was modified after you loaded it with a $elemMatch or similar projection
  • MissingSchemaError: You tried to access a model with mongoose.model() that was not defined
  • DocumentNotFoundError: The document you tried to save() was not found
  • ValidatorError: error from an individual schema path’s validator
  • ValidationError: error returned from validate() or validateSync(). Contains zero or more ValidatorError instances in .errors property.
  • MissingSchemaError: You called mongoose.Document() without a schema
  • ObjectExpectedError: Thrown when you set a nested path to a non-object value with strict mode set.
  • ObjectParameterError: Thrown when you pass a non-object value to a function which expects an object as a paramter
  • OverwriteModelError: Thrown when you call mongoose.model() to re-define a model that was already defined.
  • ParallelSaveError: Thrown when you call save() on a document when the same document instance is already saving.
  • StrictModeError: Thrown when you set a path that isn’t the schema and strict mode is set to throw.
  • VersionError: Thrown when the document is out of sync

I know the validator plugins are probably helpful, but I think the mongoose validation stuff is more intimidating than it really is complicated. It definitely looks complicated from the outside but once you start tearing into it, it’s not so bad.

If you check out the code below, you’ll see an example of how a custom error message can be returned using built-in validators.

All you have to do is set a second parameter, with your own custom error message, when setting up your fields.

Checkout the required and minlength and maxlength fields below to see how I’ve setup a custom error message, and then check out the methods below as to how the error object can be accessed or sent to the front end:

// Grab dependencies:
var mongoose = require('mongoose');

// Setup a schema:
var UserSchema = new mongoose.Schema (
    {
        username: {
            type: String,
            minlength: [2, 'Username must be at least 2 characters.'],
            maxlength: [20, 'Username must be less than 20 characters.'],
            required: [true, 'Your username cannot be blank.'],
            trim: true,
            unique: true,
            dropDups: true,
        }, // end username field
    },
    {
        timestamps: true,
    },
);

// Export the schema:
module.exports = mongoose.model('User', UserSchema);

The above sets up our fields to have custom error messages. But how do we access them or send them to our front end? We could have the following method setup in our server controller, whose response data is sent back to angular:

var myControllerMethods = {
    register : function(req, res) {
        // Create a user based on the schema we created:
        User.create(req.body)
            .then(function(newUser) {
                console.log('New User Created!', newUser);
                res.json(newUser);
            })
            .catch(function(err) {
                if (err.name == 'ValidationError') {
                    console.error('Error Validating!', err);
                    res.status(422).json(err);
                } else {
                    console.error(err);
                    res.status(500).json(err);
                }
            })
    },
};

If you ran the code above, and any of our mongoose validators did not pass, the error (err) object will be grabbed by the .catch() in the promise. If you console log this error, you’ll see in that object is our custom message, depending upon which error got flagged.

Note: The above example is just for adding custom validation messages to the already built-in validations that Mongoose possesses (like required, minlength, maxlength and so forth).

If you want to create more advanced validations, such as validating fields against regex patterns or the like, then you’ll have to create custom validator functions.

See the «Custom Validators» section at this link for a great example of how to add a validator right onto your field: http://mongoosejs.com/docs/validation.html.

Note: You can also use «pre save hooks» and «instance methods», but this is beyond the scope of this question and the built in validators and «Custom Validators» (link aforementioned) are easier routes.

Hope this helps!

Mongoose 4.5.0 introduces the ability to handle errors in middleware. This lets
you write middleware and plugins to transform errors into something useful
for your application. In other words, no more cryptic «E11000 duplicate key» errors will leak to your users if you set up
the correct middleware. If you’ve
used Express’ error handling middleware,
mongoose’s will look familiar.

An Aside On Mongoose Post Middleware

Mongoose has 2 types of middleware, «pre» middleware and «post» middleware.
Pre middleware executes before the wrapped function, and post middleware
executes after the wrapped function.

schema.pre('save', function(next) {
  console.log('before save');
  next();
});

schema.post('save', function(doc) {
  console.log('after save');
});

doc.save(); // Prints 'before save' followed by 'after save'

However, since mongoose 3.x post middleware has been interchangeable with
on() calls. In other words, schema.post('save') is the same thing as
schema.on('save'). Therefore, by design, mongoose document post middleware
does not get flow control
(query post middleware does, and in 5.0 document post middleware will too).

schema.post('save', function() {
  console.log('after save');
});

doc.save(function() {
  // May print "after save" after "save callback" or vice versa,
  // the order is undefined.
  console.log('save callback');
});

Mongoose 4.5 introduces a special type of document post middleware that
does get flow control: error handlers.

Introducing Mongoose Error Handling Middleware

You define an error handler the same way you define a normal post middleware.
To mark a post middleware as an error handler, you need to make it take 3
parameters:

var schema = new Schema({
  name: {
    type: String,
    unique: true
  }
});

// Handler **must** take 3 parameters: the error that occurred, the document
// in question, and the `next()` function
schema.post('save', function(error, doc, next) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('There was a duplicate key error'));
  } else {
    next(error);
  }
});

var Person = mongoose.model('Person', schema);

var person = { name: 'Val' };

Person.create([person, person], function(error) {
  // Will print out "There was a duplicate key error"
  console.log(error);
});

An error handler middleware only gets called when an error occurred. In
other words, the above error handler middleware will only execute if a
pre save hook called next() with an error, if save() calls back with
an error, or if a previous post hook called next() with an error.

schema.pre('save', function(next) {
  // This middleware will prevent `save()` from executing and go straight
  // to executing the error handling middleware
  next(new Error('pre save error'));
});

schema.post('save', function(doc, next) {
  // If this hook is defined _before_ an error handler middleware, this will
  // skip all other non-error-handler post save hooks and execute the next
  // error handler middleware
  next(new Error('post save error'));
});

As an aside, there are 4 functions in mongoose that can trigger a
duplicate key error: save(), insertMany(), update(), and
fineOneAndUpdate(). The create() function can also trigger a duplicate
key error, but create() is just a thin wrapper around save(). Here’s how
you can handle duplicate key errors for all these functions:

var schema = new Schema({
  name: {
    type: String,
    unique: true
  }
}, { emitIndexErrors: true });

var handleE11000 = function(error, res, next) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('There was a duplicate key error'));
  } else {
    next();
  }
};

schema.post('save', handleE11000);
schema.post('update', handleE11000);
schema.post('findOneAndUpdate', handleE11000);
schema.post('insertMany', handleE11000);

var Person = mongoose.model('Person', schema);

With this new feature, you can write plugins that can convert MongoDB-specific
errors (like the duplicate key error above) as well as mongoose-specific errors
(like validation errors) into something that makes sense for your application.

Moving On

Mongoose error handling middleware gives you a centralized mechanism for
handling errors in your application. You can use error handlers for logging
and even transforming errors, so you can standardize error formatting for your
API. I’m especially excited to see what plugins
you can write using error handling middleware.

Found a typo or error? Open up a pull request! This post is
available as markdown on Github

It is standard in Node for error events to provide one argument, which is the error itself. In my experience, even the few libraries that provide additional parameters always leave the error as the first, so that you can use a function with the signature function(err).

You can also check out the source on GitHub; here’s the pre-save hook that emits an error event, with the error as an argument, when something goes awry: https://github.com/LearnBoost/mongoose/blob/cd8e0ab/lib/document.js#L1140

There is also a pretty easy way in JavaScript to see all the arguments passed to a function:

f = ->
  console.log(arguments)

f()                     # {}
f(1, "two", {num: 3})   # { '0': 1, '1': 'two', '2': { num: 3 } }
f([1, "two", {num: 3}]) # { '0': [ 1, 'two', { num: 3 } ] }

So now to the part where your function isn’t working; how exactly does your code read? The name handleError isn’t special in any way; you’ll need one of these two:

Option 1: define the function, and pass a reference into the event registration:

handleError = (err) ->
  console.log "Got an error", err

Product.on('error', handleError)

Option 2: define the function inline:

Product.on 'error', (err) ->
  console.log "Got an error", err

Custom error messages in Mongoose can sometimes be difficult to handle, especially when dealing with MongoDB validation errors. Mongoose provides several built-in ways to handle validation errors, but these messages are often not descriptive enough or are not tailored to a specific use case. To fix this, it’s possible to create custom error messages in Mongoose that provide more context and can be better suited to a particular application. In this article, we will explore several methods to handle custom error messages in Mongoose.

Method 1: Use a custom validation function

Using a Custom Validation Function to Fix Custom Error Messages with Mongoose

You can use a custom validation function to fix custom error messages with Mongoose. Here are the steps to follow:

  1. Define your custom validation function:
const validateName = function(name) {
  return /^[a-zA-Z]+$/.test(name);
};
  1. Use your custom validation function in your schema:
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    validate: [validateName, 'Name should only contain letters']
  }
});
  1. Test your custom validation function:
const User = mongoose.model('User', userSchema);

const user = new User({ name: 'John123' });
user.save(function(error) {
  console.log(error.message); // 'Name should only contain letters'
});

In this example, we defined a custom validation function called validateName that checks if a name only contains letters. We then used this function in our schema by passing it as the second argument of the validate option. If the validation fails, Mongoose will use the error message provided as the third argument of the validate option.

Finally, we created a new User instance with an invalid name and tested our custom validation function by checking the error message that Mongoose returned.

That’s it! You can use this method to create custom validation functions for any field in your Mongoose schema.

Method 2: Use the message property in the schema

How to Fix Custom Error Messages with Mongoose using the message Property in the Schema

  1. Define your Mongoose schema with the message property for each field that needs a custom error message:
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Please enter a name'],
    message: 'Name should be a string'
  },
  age: {
    type: Number,
    required: [true, 'Please enter an age'],
    min: [18, 'Age should be greater than or equal to 18'],
    max: [120, 'Age should be less than or equal to 120']
  },
  email: {
    type: String,
    required: [true, 'Please enter an email'],
    unique: true,
    message: 'Email should be unique'
  }
});

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

module.exports = User;
  1. In your route handler or middleware, catch the Mongoose validation error and extract the error messages:
const User = require('../models/user');

const createUser = async (req, res, next) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    if (error.name === 'ValidationError') {
      const errors = {};
      Object.keys(error.errors).forEach((key) => {
        errors[key] = error.errors[key].message;
      });
      res.status(400).json({ errors });
    } else {
      next(error);
    }
  }
};

module.exports = { createUser };
  1. Test your route with invalid data to see the custom error messages:
const request = require('supertest');
const app = require('../app');

describe('POST /users', () => {
  it('should return 400 if name is missing', async () => {
    const res = await request(app)
      .post('/users')
      .send({ age: 25, email: 'john.doe@example.com' });
    expect(res.status).toBe(400);
    expect(res.body.errors.name).toBe('Please enter a name');
  });

  it('should return 400 if age is less than 18', async () => {
    const res = await request(app)
      .post('/users')
      .send({ name: 'John Doe', age: 17, email: 'john.doe@example.com' });
    expect(res.status).toBe(400);
    expect(res.body.errors.age).toBe('Age should be greater than or equal to 18');
  });

  it('should return 400 if email is not unique', async () => {
    await request(app)
      .post('/users')
      .send({ name: 'John Doe', age: 25, email: 'john.doe@example.com' });
    const res = await request(app)
      .post('/users')
      .send({ name: 'Jane Doe', age: 30, email: 'john.doe@example.com' });
    expect(res.status).toBe(400);
    expect(res.body.errors.email).toBe('Email should be unique');
  });
});

Method 3: Use the validate method in the schema

To fix custom error messages with Mongoose, you can use the validate method in the schema. This method allows you to add custom validation logic to your schema and return custom error messages when the validation fails. Here’s how you can do it:

  1. Define your schema and add the validate method to the field you want to validate:
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    validate: {
      validator: function(v) {
        return /^[a-zA-Z0-9]+$/.test(v);
      },
      message: props => `${props.value} is not a valid username!`
    }
  }
});

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

In the above example, we’re validating the username field to ensure it only contains alphanumeric characters. We’re using a regular expression to perform the validation and returning a custom error message if the validation fails.

  1. Use the validate method to validate the data before saving it to the database:
const user = new User({ username: 'invalid username!' });

user.save(function(error) {
  console.log(error.message); // 'invalid username! is not a valid username!'
});

In the above example, we’re creating a new User object with an invalid username field and attempting to save it to the database. Since the username field fails the validation, Mongoose returns a custom error message.

That’s it! You can use the validate method to add custom validation logic and error messages to any field in your Mongoose schema.

Method 4: Extend the Mongoose Error class

To extend the Mongoose Error class and customize error messages, follow these steps:

  1. Create a new file, mongoose-errors.js, and require Mongoose and the built-in util module:
const mongoose = require('mongoose');
const { format } = require('util');
  1. Create a new class that extends mongoose.Error:
class CustomError extends mongoose.Error {
  constructor(message, statusCode) {
    super();
    this.message = message;
    this.statusCode = statusCode;
  }
}
  1. Create a new function that returns a new instance of your custom error class:
function createCustomError(message, statusCode) {
  return new CustomError(message, statusCode);
}
  1. Use your custom error function to throw errors with custom messages:
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Please provide a name for this user.'],
  },
});

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

async function createUser(name) {
  try {
    const user = new User({ name });
    await user.save();
  } catch (error) {
    throw createCustomError(format('Failed to create user: %s', error.message), 500);
  }
}

In this example, the createUser function creates a new user with a required name field. If the user cannot be created, a custom error message is thrown with the original error message concatenated to the beginning.

Now you know how to extend the Mongoose Error class to create custom error messages. Happy coding!

Понравилась статья? Поделить с друзьями:
  • Mkvmerge ошибка title не хватает названия
  • Modx ошибка при обновлении
  • Mkv to mp4 выдает ошибку
  • Modx revo админка 500 ошибка
  • Mkke ошибка при запуске