0
# Error Handling
1
2
Comprehensive error system with specific error types for different failure scenarios, validation errors, and MongoDB operation errors.
3
4
## Capabilities
5
6
### Base Error Classes
7
8
Foundation error classes that other Mongoose errors extend from.
9
10
```javascript { .api }
11
/**
12
* Base class for all Mongoose errors
13
*/
14
class MongooseError extends Error {
15
/** Error name identifier */
16
name: 'MongooseError';
17
18
/** Error message */
19
message: string;
20
21
/** Error stack trace */
22
stack?: string;
23
}
24
25
/**
26
* MongoDB driver errors wrapped by Mongoose
27
*/
28
class MongoError extends Error {
29
/** MongoDB error code */
30
code?: number;
31
32
/** Error code name */
33
codeName?: string;
34
35
/** Write errors for bulk operations */
36
writeErrors?: any[];
37
38
/** Result object for failed operations */
39
result?: any;
40
}
41
```
42
43
### Validation Errors
44
45
Errors related to document validation and schema constraints.
46
47
```javascript { .api }
48
/**
49
* Document validation failure error
50
*/
51
class ValidationError extends MongooseError {
52
name: 'ValidationError';
53
54
/** Validation errors by field path */
55
errors: { [path: string]: ValidatorError };
56
57
/** Add validation error for a path */
58
addError(path: string, error: ValidatorError): void;
59
}
60
61
/**
62
* Individual field validation failure
63
*/
64
class ValidatorError extends MongooseError {
65
name: 'ValidatorError';
66
67
/** Field path that failed validation */
68
path: string;
69
70
/** Value that failed validation */
71
value: any;
72
73
/** Validator type (required, min, max, etc.) */
74
kind: string;
75
76
/** Schema type that was validated */
77
schemaType?: SchemaType;
78
79
/** Validation properties */
80
properties?: any;
81
}
82
```
83
84
**Usage Examples:**
85
86
```javascript
87
const userSchema = new mongoose.Schema({
88
name: { type: String, required: true, maxlength: 50 },
89
email: { type: String, required: true, unique: true },
90
age: { type: Number, min: 0, max: 120 }
91
});
92
93
const User = mongoose.model('User', userSchema);
94
95
try {
96
const user = new User({
97
name: '', // Too short
98
age: -5 // Below minimum
99
// email missing (required)
100
});
101
102
await user.save();
103
} catch (error) {
104
if (error instanceof mongoose.Error.ValidationError) {
105
console.log('Validation failed:', error.message);
106
107
// Access individual field errors
108
Object.keys(error.errors).forEach(path => {
109
const fieldError = error.errors[path];
110
console.log(`${path}: ${fieldError.message}`);
111
console.log(`Kind: ${fieldError.kind}, Value: ${fieldError.value}`);
112
});
113
}
114
}
115
116
// Custom validation with error handling
117
userSchema.path('email').validate(async function(email) {
118
const count = await mongoose.model('User').countDocuments({ email });
119
return count === 0;
120
}, 'Email already exists');
121
122
// Validation with custom error message
123
userSchema.path('age').validate(function(age) {
124
return age >= 13;
125
}, 'Users must be at least 13 years old');
126
```
127
128
### Cast Errors
129
130
Errors that occur when type casting fails during queries or document creation.
131
132
```javascript { .api }
133
/**
134
* Type casting failure error
135
*/
136
class CastError extends MongooseError {
137
name: 'CastError';
138
139
/** Field path where casting failed */
140
path: string;
141
142
/** Value that failed to cast */
143
value: any;
144
145
/** Target type for casting */
146
kind: string;
147
148
/** Error reason if available */
149
reason?: Error;
150
151
/** Schema type that failed to cast */
152
schemaType?: SchemaType;
153
154
/** Model associated with the error */
155
model?: Model<any>;
156
}
157
```
158
159
**Usage Examples:**
160
161
```javascript
162
try {
163
// Invalid ObjectId casting
164
const user = await User.findById('invalid-object-id');
165
} catch (error) {
166
if (error instanceof mongoose.Error.CastError) {
167
console.log('Cast error:', error.message);
168
console.log('Path:', error.path); // '_id'
169
console.log('Value:', error.value); // 'invalid-object-id'
170
console.log('Kind:', error.kind); // 'ObjectId'
171
}
172
}
173
174
try {
175
// Invalid date casting
176
const user = new User({
177
name: 'John',
178
birthDate: 'not-a-date'
179
});
180
await user.save();
181
} catch (error) {
182
if (error instanceof mongoose.Error.CastError) {
183
console.log(`Failed to cast "${error.value}" to ${error.kind} for path "${error.path}"`);
184
}
185
}
186
187
// Handle cast errors in queries
188
try {
189
const users = await User.find({ age: 'not-a-number' });
190
} catch (error) {
191
if (error instanceof mongoose.Error.CastError) {
192
console.log('Query cast error:', error.message);
193
}
194
}
195
```
196
197
### Document Operation Errors
198
199
Errors related to document operations and database interactions.
200
201
```javascript { .api }
202
/**
203
* Document not found error for operations expecting a document
204
*/
205
class DocumentNotFoundError extends MongooseError {
206
name: 'DocumentNotFoundError';
207
208
/** Query filter that found no documents */
209
filter: any;
210
211
/** Query that failed */
212
query: Query<any, any>;
213
}
214
215
/**
216
* Version conflict error for optimistic concurrency control
217
*/
218
class VersionError extends MongooseError {
219
name: 'VersionError';
220
221
/** Document that had version conflict */
222
document: Document;
223
224
/** Expected version number */
225
version: number;
226
}
227
228
/**
229
* Parallel save operation error
230
*/
231
class ParallelSaveError extends MongooseError {
232
name: 'ParallelSaveError';
233
234
/** Document being saved in parallel */
235
document: Document;
236
}
237
238
/**
239
* Error when trying to remove a document that's already being removed
240
*/
241
class ParallelValidateError extends MongooseError {
242
name: 'ParallelValidateError';
243
}
244
```
245
246
**Usage Examples:**
247
248
```javascript
249
try {
250
// Document not found error
251
const user = await User.findOneAndUpdate(
252
{ email: 'nonexistent@example.com' },
253
{ name: 'Updated Name' },
254
{
255
new: true,
256
runValidators: true,
257
context: 'query',
258
// This option causes DocumentNotFoundError if no doc found
259
upsert: false,
260
strict: false,
261
overwrite: false
262
}
263
);
264
265
if (!user) {
266
throw new mongoose.Error.DocumentNotFoundError();
267
}
268
269
} catch (error) {
270
if (error instanceof mongoose.Error.DocumentNotFoundError) {
271
console.log('Document not found:', error.filter);
272
}
273
}
274
275
// Version error handling
276
const userSchema = new mongoose.Schema({
277
name: String,
278
version: { type: Number, default: 0 }
279
});
280
281
userSchema.pre('save', function() {
282
if (this.isModified() && !this.isNew) {
283
this.increment(); // Increment version
284
}
285
});
286
287
try {
288
const user = await User.findById(userId);
289
// Simulate concurrent modification
290
setTimeout(async () => {
291
await User.findByIdAndUpdate(userId, { name: 'Changed by someone else' });
292
}, 100);
293
294
user.name = 'My change';
295
await user.save(); // May throw VersionError
296
} catch (error) {
297
if (error instanceof mongoose.Error.VersionError) {
298
console.log('Version conflict - document was modified by another process');
299
}
300
}
301
302
// Parallel save error
303
const user = new User({ name: 'John' });
304
try {
305
// Don't await both saves - this can cause ParallelSaveError
306
Promise.all([user.save(), user.save()]);
307
} catch (error) {
308
if (error instanceof mongoose.Error.ParallelSaveError) {
309
console.log('Cannot save document multiple times in parallel');
310
}
311
}
312
```
313
314
### Schema and Model Errors
315
316
Errors related to schema definition and model registration.
317
318
```javascript { .api }
319
/**
320
* Missing schema error
321
*/
322
class MissingSchemaError extends MongooseError {
323
name: 'MissingSchemaError';
324
}
325
326
/**
327
* Model overwrite error when trying to redefine existing model
328
*/
329
class OverwriteModelError extends MongooseError {
330
name: 'OverwriteModelError';
331
}
332
333
/**
334
* Schema type definition error
335
*/
336
class MongooseSchemaError extends MongooseError {
337
name: 'MongooseSchemaError';
338
}
339
340
/**
341
* Invalid schema option error
342
*/
343
class InvalidSchemaOptionError extends MongooseError {
344
name: 'InvalidSchemaOptionError';
345
346
/** Option name that was invalid */
347
option: string;
348
}
349
```
350
351
**Usage Examples:**
352
353
```javascript
354
try {
355
// Trying to create model without schema
356
const User = mongoose.model('User');
357
} catch (error) {
358
if (error instanceof mongoose.Error.MissingSchemaError) {
359
console.log('Schema is required to create a model');
360
}
361
}
362
363
try {
364
// Trying to redefine existing model
365
const User1 = mongoose.model('User', userSchema);
366
const User2 = mongoose.model('User', anotherSchema); // Error
367
} catch (error) {
368
if (error instanceof mongoose.Error.OverwriteModelError) {
369
console.log('Cannot overwrite model once registered');
370
// Use mongoose.deleteModel() first, or pass { overwriteModels: true }
371
}
372
}
373
374
// Schema definition errors
375
try {
376
const invalidSchema = new mongoose.Schema({
377
name: {
378
type: String,
379
invalidOption: true // This might cause schema error
380
}
381
});
382
} catch (error) {
383
if (error instanceof mongoose.Error.MongooseSchemaError) {
384
console.log('Schema definition error:', error.message);
385
}
386
}
387
```
388
389
### Connection and Server Errors
390
391
Errors related to database connections and server communication.
392
393
```javascript { .api }
394
/**
395
* Server selection error when unable to connect to MongoDB
396
*/
397
class MongooseServerSelectionError extends MongooseError {
398
name: 'MongooseServerSelectionError';
399
400
/** Reason for server selection failure */
401
reason?: Error;
402
}
403
404
/**
405
* Connection timeout error
406
*/
407
class MongooseTimeoutError extends MongooseError {
408
name: 'MongooseTimeoutError';
409
}
410
411
/**
412
* Disconnected error when operation attempted on closed connection
413
*/
414
class DisconnectedError extends MongooseError {
415
name: 'DisconnectedError';
416
}
417
418
/**
419
* Strict mode violation error
420
*/
421
class StrictModeError extends MongooseError {
422
name: 'StrictModeError';
423
424
/** Path causing strict mode violation */
425
path: string;
426
427
/** Invalid value */
428
value: any;
429
}
430
431
/**
432
* Populate path doesn't exist in strict populate mode
433
*/
434
class StrictPopulateError extends MongooseError {
435
name: 'StrictPopulateError';
436
437
/** Population path */
438
path: string;
439
}
440
441
/**
442
* Bulk save operations incomplete error
443
*/
444
class MongooseBulkSaveIncompleteError extends MongooseError {
445
name: 'MongooseBulkSaveIncompleteError';
446
447
/** Failed operations */
448
failedOperations: any[];
449
}
450
```
451
452
**Usage Examples:**
453
454
```javascript
455
try {
456
await mongoose.connect('mongodb://invalid-host:27017/myapp', {
457
serverSelectionTimeoutMS: 5000
458
});
459
} catch (error) {
460
if (error instanceof mongoose.Error.MongooseServerSelectionError) {
461
console.log('Could not connect to MongoDB server');
462
console.log('Reason:', error.reason?.message);
463
}
464
}
465
466
// Handle connection errors
467
mongoose.connection.on('error', (error) => {
468
if (error instanceof mongoose.Error.MongooseTimeoutError) {
469
console.log('Database operation timed out');
470
} else if (error instanceof mongoose.Error.DisconnectedError) {
471
console.log('Database connection lost');
472
}
473
});
474
475
// Retry logic for connection errors
476
async function connectWithRetry() {
477
const maxRetries = 3;
478
let retries = 0;
479
480
while (retries < maxRetries) {
481
try {
482
await mongoose.connect(process.env.MONGODB_URI);
483
console.log('Connected to MongoDB');
484
break;
485
} catch (error) {
486
if (error instanceof mongoose.Error.MongooseServerSelectionError) {
487
retries++;
488
console.log(`Connection attempt ${retries} failed, retrying...`);
489
await new Promise(resolve => setTimeout(resolve, 1000 * retries));
490
} else {
491
throw error; // Re-throw non-connection errors
492
}
493
}
494
}
495
}
496
```
497
498
### Error Handling Patterns
499
500
Common patterns for handling Mongoose errors in applications.
501
502
```javascript { .api }
503
// Error handling middleware for Express.js
504
function handleMongooseError(error, req, res, next) {
505
if (error instanceof mongoose.Error.ValidationError) {
506
return res.status(400).json({
507
type: 'ValidationError',
508
message: 'Validation failed',
509
errors: Object.keys(error.errors).map(path => ({
510
path,
511
message: error.errors[path].message,
512
value: error.errors[path].value
513
}))
514
});
515
}
516
517
if (error instanceof mongoose.Error.CastError) {
518
return res.status(400).json({
519
type: 'CastError',
520
message: `Invalid ${error.kind}: ${error.value}`,
521
path: error.path
522
});
523
}
524
525
if (error instanceof mongoose.Error.DocumentNotFoundError) {
526
return res.status(404).json({
527
type: 'DocumentNotFoundError',
528
message: 'Document not found'
529
});
530
}
531
532
if (error.code === 11000) { // MongoDB duplicate key error
533
return res.status(409).json({
534
type: 'DuplicateKeyError',
535
message: 'Duplicate key error',
536
keyValue: error.keyValue
537
});
538
}
539
540
// Generic server error
541
res.status(500).json({
542
type: 'InternalServerError',
543
message: 'An unexpected error occurred'
544
});
545
}
546
```
547
548
**Usage Examples:**
549
550
```javascript
551
// Comprehensive error handling in async functions
552
async function createUser(userData) {
553
try {
554
const user = new User(userData);
555
await user.save();
556
return { success: true, user };
557
} catch (error) {
558
if (error instanceof mongoose.Error.ValidationError) {
559
return {
560
success: false,
561
type: 'validation',
562
errors: Object.keys(error.errors).map(path => ({
563
field: path,
564
message: error.errors[path].message,
565
value: error.errors[path].value
566
}))
567
};
568
}
569
570
if (error.code === 11000) { // Duplicate key (unique constraint)
571
return {
572
success: false,
573
type: 'duplicate',
574
message: 'Email already exists'
575
};
576
}
577
578
// Re-throw unexpected errors
579
throw error;
580
}
581
}
582
583
// Promise-based error handling
584
User.create(userData)
585
.then(user => {
586
console.log('User created:', user);
587
})
588
.catch(error => {
589
if (error instanceof mongoose.Error.ValidationError) {
590
console.log('Validation errors:', error.errors);
591
} else {
592
console.error('Unexpected error:', error);
593
}
594
});
595
596
// Using async/await with try-catch
597
async function updateUser(id, updateData) {
598
try {
599
const user = await User.findByIdAndUpdate(
600
id,
601
updateData,
602
{ new: true, runValidators: true }
603
);
604
605
if (!user) {
606
throw new mongoose.Error.DocumentNotFoundError();
607
}
608
609
return user;
610
} catch (error) {
611
if (error instanceof mongoose.Error.CastError && error.path === '_id') {
612
throw new Error('Invalid user ID format');
613
}
614
615
if (error instanceof mongoose.Error.ValidationError) {
616
const validationErrors = Object.values(error.errors).map(err => err.message);
617
throw new Error(`Validation failed: ${validationErrors.join(', ')}`);
618
}
619
620
throw error; // Re-throw other errors
621
}
622
}
623
```
624
625
## Types
626
627
```javascript { .api }
628
// Error type union for comprehensive error handling
629
type MongooseErrorTypes =
630
| MongooseError
631
| ValidationError
632
| ValidatorError
633
| CastError
634
| DocumentNotFoundError
635
| VersionError
636
| ParallelSaveError
637
| MissingSchemaError
638
| OverwriteModelError
639
| MongooseServerSelectionError
640
| MongooseTimeoutError
641
| DisconnectedError;
642
643
interface ErrorHandlerOptions {
644
/** Transform error before throwing */
645
transform?: (error: Error) => Error;
646
647
/** Custom error messages by error type */
648
messages?: { [errorType: string]: string };
649
650
/** Additional context for error reporting */
651
context?: any;
652
}
653
654
// Error event types for connection monitoring
655
interface ConnectionErrorEvents {
656
'error': (error: Error) => void;
657
'disconnected': () => void;
658
'reconnectFailed': () => void;
659
'timeout': () => void;
660
'close': () => void;
661
}
662
```