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

Validation

Before we get into the specifics of validation syntax, please keep the following rules in mind:

  • Validation is defined in the SchemaType
  • Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default.
  • Validation always runs as the first pre('save') hook. This means that validation doesn’t run on any changes you make in pre('save') hooks.
  • You can disable automatic validation before save by setting the validateBeforeSave option
  • You can manually run validation using doc.validate() or doc.validateSync()
  • You can manually mark a field as invalid (causing validation to fail) by using doc.invalidate(...)
  • Validators are not run on undefined values. The only exception is the required validator.
  • When you call Model#save, Mongoose also runs subdocument validation. If an error occurs, your Model#save promise rejects
  • Validation is customizable
  • Built-in Validators
  • Custom Error Messages
  • The unique Option is Not a Validator
  • Custom Validators
  • Async Custom Validators
  • Validation Errors
  • Cast Errors
  • Global SchemaType Validation
  • Required Validators On Nested Objects
  • Update Validators
  • Update Validators and this
  • Update Validators Only Run On Updated Paths
  • Update Validators Only Run For Some Operations

Built-in Validators

Mongoose has several built-in validators.

  • All SchemaTypes have the built-in required validator. The required validator uses the SchemaType’s checkRequired() function to determine if the value satisfies the required validator.
  • Numbers have min and max validators.
  • Strings have enum, match, minLength, and maxLength validators.

Each of the validator links above provide more information about how to enable them and customize their error messages.

[require:Built-in Validators]

Custom Error Messages

You can configure the error message for individual validators in your schema. There are two equivalent
ways to set the validator error message:

  • Array syntax: min: [6, 'Must be at least 6, got {VALUE}']
  • Object syntax: enum: { values: ['Coffee', 'Tea'], message: '{VALUE} is not supported' }

Mongoose also supports rudimentary templating for error messages.
Mongoose replaces {VALUE} with the value being validated.

[require:Custom Error Messages]

The unique Option is Not a Validator

A common gotcha for beginners is that the unique option for schemas
is not a validator. It’s a convenient helper for building MongoDB unique indexes.
See the FAQ for more information.

[require:The `unique` Option is Not a Validator]

Custom Validators

If the built-in validators aren’t enough, you can define custom validators
to suit your needs.

Custom validation is declared by passing a validation function.
You can find detailed instructions on how to do this in the
SchemaType#validate() API docs.

[require:Custom Validators]

Async Custom Validators

Custom validators can also be asynchronous. If your validator function
returns a promise (like an async function), mongoose will wait for that
promise to settle. If the returned promise rejects, or fulfills with
the value false, Mongoose will consider that a validation error.

[require:Async Custom Validators]

Validation Errors

Errors returned after failed validation contain an errors object
whose values are ValidatorError objects. Each
ValidatorError has kind, path,
value, and message properties.
A ValidatorError also may have a reason property. If an error was
thrown in the validator, this property will contain the error that was
thrown.

[require:Validation Errors]

Cast Errors

Before running validators, Mongoose attempts to coerce values to the
correct type. This process is called casting the document. If
casting fails for a given path, the error.errors object will contain
a CastError object.

Casting runs before validation, and validation does not run if casting
fails. That means your custom validators may assume v is null,
undefined, or an instance of the type specified in your schema.

Global SchemaType Validation

In addition to defining custom validators on individual schema paths, you can also configure a custom validator to run on every instance of a given SchemaType.
For example, the following code demonstrates how to make empty string '' an invalid value for all string paths.

[require:Global SchemaType Validation]

Required Validators On Nested Objects

Defining validators on nested objects in mongoose is tricky, because
nested objects are not fully fledged paths.

[require:Required Validators On Nested Objects]

Update Validators

In the above examples, you learned about document validation. Mongoose also
supports validation for update(),
updateOne(),
updateMany(),
and findOneAndUpdate() operations.
Update validators are off by default — you need to specify
the runValidators option.

To turn on update validators, set the runValidators option for
update(), updateOne(), updateMany(), or findOneAndUpdate().
Be careful: update validators are off by default because they have several
caveats.

[require:Update Validators$]

Update Validators and this

There are a couple of key differences between update validators and
document validators. In the color validation function below, this refers
to the document being validated when using document validation.
However, when running update validators, this refers to the query object instead of the document.
Because queries have a neat .get() function, you can get the updated value of the property you want.

[require:Update Validators and `this`]

Update Validators Only Run On Updated Paths

The other key difference is that update validators only run on the paths
specified in the update. For instance, in the below example, because
‘name’ is not specified in the update operation, update validation will
succeed.

When using update validators, required validators only fail when
you try to explicitly $unset the key.

[require:Update Validators Only Run On Updated Paths]

Update Validators Only Run For Some Operations

One final detail worth noting: update validators only run on the
following update operators:

  • $set
  • $unset
  • $push
  • $addToSet
  • $pull
  • $pullAll

For instance, the below update will succeed, regardless of the value of
number, because update validators ignore $inc.

Also, $push, $addToSet, $pull, and $pullAll validation does
not run any validation on the array itself, only individual elements
of the array.

[require:Update Validators Only Run For Some Operations]

Next Up

Now that we’ve covered Validation, let’s take a look at Middleware.

I’m creating an API using Restify and Mongoose, and I’m completely new to both. I can’t seem to figure out the proper way to handle errors in Mongoose / Node.

As of now, I’m trying to do something like this:

Submission.findById(req.params.submission_id, function(err, data) {

    if (err) 
        return next(err);

    res.send(data);

});

I’m attempting to call a GET on this (for a user that not exist). And rather than sending back a simple error message, it causes my entire node application to fail. I’m a bit confused on the user of return next(err) and what that exactly should do.

Any help is greatly appreciated.

asked Jan 14, 2013 at 17:16

Nick Parsons's user avatar

Nick ParsonsNick Parsons

8,33613 gold badges47 silver badges70 bronze badges

A findById query that doesn’t find a match isn’t an error at the Mongoose level, so you if you want it treated that way you have to do it yourself:

Submission.findById(req.params.submission_id, function(err, data) {

    if (err)
        return next(err);
    else if (!data)
        return next(new Error("User not found"));

    res.send(data);

});

answered Jan 14, 2013 at 17:47

JohnnyHK's user avatar

2

Понравилась статья? Поделить с друзьями:
  • Moodle ошибка 1007
  • Mom exe системная ошибка
  • Monster hunter rise неустранимая ошибка приложения
  • Mom exe ошибка приложения
  • Monster hunter rise неустранимая ошибка d3d