2
votes

Mongoose emits a stack trace for a cast error. I know how to prevent the Mongoose error - please do not answer how to prevent the error.

How can I stop Mongoose emitting stack trace errors in production?

Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters at new ObjectID (c:\proj\fboapp\node_modules\mongoose\node_modules\bson\lib\bson\objectid.js:38:11) at c:\proj\fboapp\routes\user\no_auth_user_api_routes.js:135:27 at Layer.handle [as handle_request] (c:\proj\fboapp\node_modules\express\lib\router\layer.js:95:5) at next (c:\proj\fboapp\node_modules\express\lib\router\route.js:131:13) at Route.dispatch (c:\proj\fboapp\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (c:\proj\fboapp\node_modules\express\lib\router\layer.js:95:5) at c:\proj\fboapp\node_modules\express\lib\router\index.js:277:22 at Function.process_params (c:\proj\fboapp\node_modules\express\lib\router\index.js:330:12) at next (c:\proj\fboapp\node_modules\express\lib\router\index.js:271:10) at Function.handle (c:\proj\fboapp\node_modules\express\lib\router\index.js:176:3) at router (c:\proj\fboapp\node_modules\express\lib\router\index.js:46:12) at Layer.handle [as handle_request] (c:\proj\fboapp\node_modules\express\lib\router\layer.js:95:5) at trim_prefix (c:\proj\fboapp\node_modules\express\lib\router\index.js:312:13) at c:\proj\fboapp\node_modules\express\lib\router\index.js:280:7 at Function.process_params (c:\proj\fboapp\node_modules\express\lib\router\index.js:330:12) at next (c:\proj\fboapp\node_modules\express\lib\router\index.js:271:10)

Nodejs v0.12.3 Mongoose v4.4.3

2
Do u really want to do this? This is a bug in your app, and this should be fixed. But if you still want - create event for that error type and handle it...loadaverage
I want to prevent emitting errors to the browser api in production for security. The bug is fixed - I simply pasted the error code to demonstrate the stack trace.steampowered
Oh, so that's actually throw statement in mongoose. So, there are no way to "hide" it, except using try ... catch as I know.loadaverage
btw, are u using express? is so, express can handle errors wellloadaverage
Here is one module, github.com/Faleij/mongoose-disable-stack-trace, you can try it.zangw

2 Answers

2
votes

Generally speaking, add try-catch block in the codes could be correct way to do it.

Here are my test codes without try-catch block in codes, then prevent stack trace. Refer to this module mongoose disable stack trace, also add some new errors are added into mongoose, and set Error.stackTraceLimit to 0 will disable stack trace collection.


index.js

const captureStackTrace = Error.captureStackTrace;
const CastError = module.parent.require('mongoose/lib/error/cast');
const VersionError = module.parent.require('mongoose/lib/error/version');
const ValidatorError = module.parent.require('mongoose/lib/error/validator');
const ValidationError = module.parent.require('mongoose/lib/error/validation');
const OverwriteModelError = module.parent.require('mongoose/lib/error/overwriteModel');
const MissingSchemaError = module.parent.require('mongoose/lib/error/missingSchema');
const DivergentArrayError = module.parent.require('mongoose/lib/error/divergentArray');

Error.captureStackTrace = function( that, params) {
    if(that instanceof CastError ||
        that instanceof VersionError ||
        that instanceof ValidatorError ||
        that instanceof ValidationError ||
        that instanceof OverwriteModelError ||
        that instanceof MissingSchemaError ||
        that instanceof DivergentArrayError) {
        Error.stackTraceLimit = 0;
    } else if (typeof that !== 'undefined'){
        captureStackTrace.apply(Error, arguments);
    }     
}

Error.captureStackTrace(new VersionError);

app.js

require('mongoose-disable-stack-trace');
var f = Foo({_id: new ObjectId('adss112'), key: '123'}); // invalid ObjectId

Output:

Error: Argument passed in must be a single String of 12 bytes or a string of 24
hex characters
c:\share\node\node_modules\mongoose\node_modules\mongodb\lib\server.js:283
      process.nextTick(function() { throw err; })                                  ^

Error: Argument passed in must be a single String of 12 bytes or a string of 24
hex characters
2
votes

I was confused about why errors were being rendered to the browser without an error handler, until I read the ExpressJS error handling documentation page.

Apparently there is a default error handler which is triggered when no error handler is specified.

Express comes with an in-built error handler, which takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.

The best practice is to specify a custom error handler for production which does not output the stack trace to the browser. The default error handler always outputs the stack trace to the browser.

There is no need for try-catch blocks to route uncaught errors to the custom error handler, because Express will automatically route uncaught errors to the error handler. Also note: error handler middleware MUST specify all 4 arguments: err, req, res and next

An example of a custom error handler:

app.use(function(err, req, res, next) {
        res.send('uncaught error in production');
});