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’stype
, like'required'
or'regexp'
path
: The path that failed validationvalue
: 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 errorCastError
: Mongoose could not convert a value to the type defined in the schema path. May be in aValidationError
class’errors
property.DivergentArrayError
: You attempted tosave()
an array that was modified after you loaded it with a$elemMatch
or similar projectionMissingSchemaError
: You tried to access a model withmongoose.model()
that was not definedDocumentNotFoundError
: The document you tried tosave()
was not foundValidatorError
: error from an individual schema path’s validatorValidationError
: error returned fromvalidate()
orvalidateSync()
. Contains zero or moreValidatorError
instances in.errors
property.MissingSchemaError
: You calledmongoose.Document()
without a schemaObjectExpectedError
: 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 paramterOverwriteModelError
: Thrown when you callmongoose.model()
to re-define a model that was already defined.ParallelSaveError
: Thrown when you callsave()
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 tothrow
.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 inpre('save')
hooks. - You can disable automatic validation before save by setting the validateBeforeSave option
- You can manually run validation using
doc.validate()
ordoc.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
andmax
validators. - Strings have
enum
,match
,minLength
, andmaxLength
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 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
2