Suppressing/Catching the ValidationError error from Mongoose - mongodb

I have a static method setup that will verify if an object follows the schema of the model properly, and I've got the validation itself working just fine, but I can't get Mongoose to hide the ValidationError error that displays in the console.
The static method for the validation is:
fieldSchema.statics.testValidate = function( field ) {
return new Promise( ( res, rej ) => {
new this( field ).validate( err => {
if ( err ) return rej( err )
res( true )
} )
})
}
Then when I execute it:
Field.testValidate( fieldData )
.then(data => {
console.log('OK!', data)
})
.catch( err => {
console.error('FAILED:',err)
})
.finally(() => Mongoose.connection.close())
And like I said, I can get it to validate the data, but it will always show this error:
Unhandled rejection ValidationError: Field validation failed
at MongooseError.ValidationError ....
(Note: Im using Bluebird for my JS promises, incase it has anything to do with the then/catch somehow)
The script execution keeps going on with the code, so that means that it doesnt actually kill the script or anything, it just logs the error to the console. But since this function is meant to validate, its not really an "error", so is there a way to hide this from the console? (Just for this function, not for ALL Mongoose errors)
Thanks

validate already returns a promise so you don't need to wrap it in a new promise. The reason you see the error logged to the console is because of the fact that you're wrapping it in a new promise thus preventing the original promise from ever being caught i.e. Unhandled rejection.
fieldSchema.statics.testValidate = function(fieldData) {
return new this(fieldData).validate()
}

Related

Is there a way to get rid of the Runaway Promise warning when using react-query

I am using react-query useQuery as follows:
const { isLoading, error, data } = useQuery('repoData', () => {
return fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
res.json()
)
}
)
It generates the following warning:
Warning: a promise was created in a handler at webpack-internal:///./node_modules/react-query/es/core/retryer.js:68:50 but was not returned from it.
Is there anyway to remove it.
I am using Typescript

How to handle non explicit errors inside sails.js helpers?

I am trying to figure out how the Error handling in Sails.js works. Unfortunatley the code examples in the docs do not cover this use case.
The problem is I keep getting this error:
UsageError: `.intercept()` handler returned `undefined`, but this should never happen.
Regardless, here is a summary of the original underlying error:
Now all I am trying to do is call a helper and if it fails, then I want to catch the error (any), log it and run some code. If I wouldn't be using Sails but normal promises I would have handled it like this:
await helper().catch((err) => { // run some code }
In Sails I should be able to use .intercept() instead of .catch()
My code looks like this:
// ExportController.js
const csv = await sails.helpers.files.convertToCsv(data)
.intercept((err) => {
sails.log.error(err)
req.addFlash('error_messages', 'Error parsing data to csv!')
return res.redirect(`/`);
})
// convert-to-csv.js
if (!Array.isArray(inputs.data)) {
throw new Error('invalid inputs.data type: ' + typeof inputs.data)
};
Now how can I avoid getting this error?
The code examples show only cases where errors that are explicitly added to the exits object are handled, but not for general error handling.
In the docs it says that if the filter argument is
not provided, ALL errors will be intercepted.
Or is that only true for db queries? Because the .intercept() doc section is in that subcategory.
You could use “throw ‘errorCode’;” for example:
Set the exits:
exits {
errorWithCsvFile: {
responseType: 'badRequest'
}
}
const csv = await sails.helpers.files.convertToCsv(data)
.intercept(‘somethingWrongCode’, ‘errorWithCsvFile’)
... // Other handles
.intercept(err => new Error(err))
Alternative:
try {
...
const csv = await sails.helpers.files.convertToCsv(data)
.intercept((err) => {
sails.log.error(err)
req.addFlash('error_messages', 'Error parsing data to csv!')
throw 'badRequest';
})
...
} catch (err) {
sails.log.err(err);
return res.redirect(`/`);
}

TypeError seneca indexof if not a function during respond

I have written a simple action which connects to mongo db using seneca-mongo store module, execute a list query and get the results. I can see that the query was successful and the correct results were fetched. When I try to send these results back to the client, the respond call errors out with following message and stack trace.
ERROR act root$ OUT cmd:getparams,role:diff 11 {cmd:getparams,role:diff,payload:{id:scalaScan}} ENTRY (dqk22) - seneca: Action cmd:getparams,role:diff callback threw: k.indexOf is not a function. act_callback {message:k.indexOf is not a function,pattern:cmd:getparams,role:diff,instance:Seneca/0.7.2/d0twcki9cmxg/1485517 TypeError: k.indexOf is not a function
at /scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:851:13
at Function.forEach (/scratch/DiffAnalyzer/node_modules/lodash/dist/lodash.js:3298:15)
at Object.defaultmodify [as modify] (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:850:7)
at respond (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:654:22)
at Seneca.<anonymous> (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:401:7)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at Seneca.<anonymous> (/scratch/DiffAnalyzer/analyze.js:613:5)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at /scratch/DiffAnalyzer/node_modules/seneca-mongo-store/mongo-store.js:329:21
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:271:33
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:35
at Cursor.close (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:1009:5)
at Cursor.nextObject (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:17)
at Cursor.each (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:264:12)
The action that I have written is
seneca.add("role:diff,cmd:getparams", function(msg, respond) {
seneca.ready(function() {
var collection = seneca.make$("paramStore");
var f = msg.payload;
seneca.log.info("Filter", f);
collection.list$(f, function(err, ob) {
if (err) {
seneca.log.error(err);
respond(err);
} else {
seneca.log.info("Result", ob);
respond(null, ob);
}
});
});
});
The same piece of code was working and now I am getting this error. Not sure what changed. Any help/suggestions are greatly appreciated.
The issue I was facing was because of this bit of code in the module's js file
if( _.isObject( result.out ) ) {
_.each(result.out,function(v,k){
if(~k.indexOf('$') && 'http$' !== k) {
delete result.out[k]
}
})
The _.each function is meant to parse a JSON object, where in my case the out was actually a JSON array. Wrapping the array into an object resolved it.

Mongoose: Consume error in post hook

I have an Express.js app backed with MongoDB using Mongoose. I need to ignore a duplicate key error from MongoDB (error code 11000) and still return a 204 HTTP response. The idea is to use the post hook on save, consume the error and ignore it.
Service layer
const createMyModel = (req, res, next) => {
MyModel.create({...data})
.then(createRes => res.status(204).send())
.catch(next)
}
Schema - save hook
MySchema.post('save', (err, res, next) => {
if (!err || (err.name === 'MongoError' && err.code === 11000)) {
// The duplicate key error is caught here but somehow
// the catch on my service layer gets triggered
next();
}else{
next(err)
}
});
The next callback in Mongoose keeps track of something called a firstError. This is where internal errors like Duplicate Key Error get stored. This prevents the user from overriding the error state and calling next would always result in checking for firstError and triggering a promise rejection even if one tries to call next() or next(null).
If you want to ignore them completely I think you could set emitIndexErrors to false in the schema.options object.
http://mongoosejs.com/docs/guide.html#emitIndexErrors

Error handling with Mongoose

I am an absolute NodeJS beginner and want to create a simple REST-Webservice with Express and Mongoose.
Whats the best practice to handle errors of Mongoose in one central place?
When anywhere an database error occurs I want to return a Http-500-Error-Page with an error message:
if(error) {
res.writeHead(500, {'Content-Type': 'application/json'});
res.write('{error: "' + error + '"}');
res.end();
}
In the old tutorial http://blog-next-stage.learnboost.com/mongoose/ I read about an global error listener:
Mongoose.addListener('error',function(errObj,scope_of_error));
But this doesn't seem to work and I cannot find something in the official Mongoose documentation about this listener. Have I check for errors after every Mongo request?
If you're using Express, errors are typically handled either directly in your route or within an api built on top of mongoose, forwarding the error along to next.
app.get('/tickets', function (req, res, next) {
PlaneTickets.find({}, function (err, tickets) {
if (err) return next(err);
// or if no tickets are found maybe
if (0 === tickets.length) return next(new NotFoundError));
...
})
})
The NotFoundError could be sniffed in your error handler middleware to provide customized messaging.
Some abstraction is possible but you'll still require access to the next method in order to pass the error down the route chain.
PlaneTickets.search(term, next, function (tickets) {
// i don't like this b/c it hides whats going on and changes the (err, result) callback convention of node
})
As for centrally handling mongoose errors, theres not really one place to handle em all. Errors can be handled at several different levels:
connection errors are emitted on the connection your models are using, so
mongoose.connect(..);
mongoose.connection.on('error', handler);
// or if using separate connections
var conn = mongoose.createConnection(..);
conn.on('error', handler);
For typical queries/updates/removes the error is passed to your callback.
PlaneTickets.find({..}, function (err, tickets) {
if (err) ...
If you don't pass a callback the error is emitted on the Model if you are listening for it:
PlaneTickets.on('error', handler); // note the loss of access to the `next` method from the request!
ticket.save(); // no callback passed
If you do not pass a callback and are not listening to errors at the model level they will be emitted on the models connection.
The key take-away here is that you want access to next somehow to pass the error along.
hey this is the simplest way i found..
try { } catch (error) {
console.log(error);
// checking validation
if (error.name === "ValidationError") {
const message = Object.values(error.errors).map(value => value.message);
return res.status(400).json({
error: message
})
}
res.status(400).json(error.message)
}
}
just copy paste