As most of you know sails.js framework throws error as WLError object, I would like to make this consistent across my application. Any I error I would like to raise in my services should be a WLError object with my own error,status & summary. Has anyone done this?
var error = new Error(errorMsg);
return error;
I want something like below...
var error = new WLError({"status":"Fail", "error": "somethig", "summary": "OOPS!!"});
return error;
Thanks!
In one of my adapters I use waterline errors
// Adjust the relative path as needed
var WLError = require('../../sails/node_modules/waterline/lib/waterline/error/WLError');
processError: function(error) {
var formattedErr = new WLError();
formattedErr.code = 'E_MY_ERROR';
formattedErr.status = 400;
formattedErr.reason = error;
formattedErr.details = error;
return formattedErr;
},
Also I did just the opposite, converting waterline errors to look like other sails errors
in api/responses/badRequest.js I added:
// If the user-agent wants JSON, always respond with JSON
if (req.wantsJSON) {
try {
// This formats waterline errors like other sails errors
// See WLError.prototype.toJSON in waterline/error/WLError.js
var WLResponse = data.toJSON();
if(WLResponse.hasOwnProperty('error') && WLResponse.hasOwnProperty('summary')) {
return res.jsonx({
code: WLResponse.error,
message: WLResponse.summary
});
} else {
// Not a waterline error
throw 'NonWLError';
}
} catch (e) {
return res.jsonx(data);
}
}
I did this...
I added below in bootstrap.js
sails.WLError = require('../node_modules/sails/node_modules/waterline/lib/waterline/error/WLError.js');
Then in my code need not do a "require". Just below lines works.
error = new sails.WLError();
error.code = "404";
error.status = "Failure";
error.summary = "Invalid Request";
error.details = errorMsg;
Related
Hello and thank you for taking a look at this.
I have a scheduled function that contacts an API and is supposed to save the data to a local DB. It works several times and then stops saving. I have confirmed that the functions are executing per their scheduled times. Mongoose does not save the data and does not give me an error.
2 part request:
I would love help trying to catch and log the error.
-Maybe my logger(s) are in the wrong location?
Also, if you have any insight as to why it works when I start the
server and then eventually stops working that would be appreciated as
well.
-Maybe I am not 'returning' the functions properly?
Get the data from the API:
function updateWeather(){
const weatherurl = 'https://api.aerisapi.com/observations/pendleton,or?&format=json&filter=allstations&limit=1&client_id=bRZUxQc8j4z41CrH7SM6u&client_secret=GaEA7lMyLKnQwRsUcxv1mnNhTUkx6KUtVsrIXVcR';
axios.get(weatherurl)
.then(response=>{
// console.log(response.data);
let condition = response.data.response.ob.weather,
temp = response.data.response.ob.tempF,
windDir = response.data.response.ob.windDir,
windSpd = response.data.response.ob.windSpeedMPH,
windGust = response.data.response.ob.windGustMPH,
windChill = response.data.response.ob.windchillF,
humidity = response.data.response.ob.humidity,
icon = response.data.response.ob.icon,
date = moment().utcOffset(-8).format('YYYY-MM-DD'),
updated = moment().utcOffset(-8).format('MM/DD/YY HH:mm');
if(temp <= 35){
var tempIcon = 'https://cdn.aerisapi.com/wxicons/v2/cold.png';
}else if(temp >= 80){
var tempIcon = 'https://cdn.aerisapi.com/wxicons/v2/hot.png';
}else{
var tempIcon = '';
}
currentWeather.push({date:date, condition:condition, temp:temp, windChill:windChill, windDir:windDir, windSpd:windSpd, windGust:windGust, humidity:humidity, icon:icon, tempIcon:tempIcon, updated:updated});
return currentWeather[0]
}).then(currentWeather=>{
// console.log(currentWeather);
saveWeather(currentWeather);
}).catch(error=>{
logger.error(error);
});
return currentWeather;
}
Save data to DB:
function saveWeather(weather){
logger.info('saveWeather connection status: '+mongoose.connection.readyState);
if(mongoose.connection.readyState !== 1){
mongoose.connect("mongodb://localhost:27017/fdData", {useNewUrlParser: true});
}
Weather.updateOne({date: weather.date}, {date:weather.date, condition:weather.condition, temp:weather.temp, windChill:weather.windChill, windDir:weather.windDir, windSpd:weather.windSpd, windGust:weather.windGust, humidity:weather.humidity, icon:weather.icon, tempIcon:weather.tempIcon, updated:weather.updated}, {upsert:true}, error=> {
if (error){
logger.error(error);
} else{
logger.info('Weather Saved to DB')
}
})
return weather;
}
Thanks again!
-Adam
I use the Pre sign-up trigger of Cognito to validate the user registration. If some validation fails the function responses with a custom error. The client only receive the UserLambdaValidationException as ErrorCode.
Is there a way to receive the custom error name instead?
Current using sample:
exports.handler = function(event, context, callback) {
function AccountAlreadyExistsError(message) {
this.name = "AccountAlreadyExistsError";
this.message = message;
}
AccountAlreadyExistsError.prototype = new Error();
const error = new AccountAlreadyExistsError("Account is in use!");
callback(error);
};
I want to get AccountAlreadyExistsError in our client instead of UserLambdaValidationException.
You can customise exception headers only if it is a Lambda Proxy, with the API Gateway (x-amzn-errortype header), in any other case you need to parse the exception message to get your custom exception, here is an example how I manage exceptions for Cognito lambda triggers, it's just to show you the idea:
/*
Lambda Code, could be in a Lambda layer
*/
const EXCEPTION_TYPE_DELIMITER = "etype"
const EXCEPTION_MESSAGE_DELIMITER = "emsg";
const beTagged = (tag, txt) => {
return "<" + tag + ">" + txt + "</" + tag + ">";
};
class UserNotAllowedException extends Error {
constructor (message) {
super(beTagged(EXCEPTION_MESSAGE_DELIMITER, message))
Error.captureStackTrace(this, this.constructor);
this.name = beTagged(EXCEPTION_TYPE_DELIMITER, this.constructor.name);
}
}
exports.handler = async (event, context, callback) => {
// Your logic, etc..
throw new UserNotAllowedException("You are blocked :(");
}
Here is the parser
/*
Client Code
*/
const EXCEPTION_TYPE_DELIMITER_REGEX = /<etype>(.*?)<\/etype>/g;
const EXCEPTION_TYPE_UNTAG_REGEX = /<\/?etype>/g;
const EXCEPTION_MESSAGE_DELIMITER_REGEX = /<emsg>(.*?)<\/emsg>/g;
const EXCEPTION_MESSAGE_UNTAG_REGEX = /<\/?emsg>/g;
const untag = (txt, delimiterRegex, untagRegex) => {
return txt.match(delimiterRegex).map(etype => {
return etype.replace(untagRegex,"");
})[0];
};
const resolveException = (exceptionMessage) => {
const exceptionType = untag(exceptionMessage, EXCEPTION_TYPE_DELIMITER_REGEX, EXCEPTION_TYPE_UNTAG_REGEX);
const exceptionMessage = untag(exceptionMessage, EXCEPTION_MESSAGE_DELIMITER_REGEX, EXCEPTION_MESSAGE_UNTAG_REGEX);
// Your logic to determine what exception is the exceptionType
return new YourResolvedException(exceptionMessage);
};
try {
// This guy should throw the exception
return await Auth.signUp(params);
} catch (e) {
// Expected message from Cognito Lambda Trigger
// PreSignUp failed with error <etype>UserNotAllowedException</etype>: <emsg>You are blocked :(</emsg>.
// For example, here your custom exception resolver
throw resolveException(e.message);
}
It can be done in a thousand ways, but the best thing for us would be if the AWS services were able to fully customise the exceptions without so much hassle.
Regards!
I tried it on my end and was able to get the error message in the client. Tested it using AWS CLI, Nodejs & the built-in Cognito UI. I returned the error using:
var error = new Error('something went wrong..!');
callback(error,event);
I got the error UserLambdaValidationException: PreSignUp failed with error something went wrong..! in all my clients. Even callback(error) worked.
I'm parsing the URL input to a function using the URL module in node.
If a relative path is given a TypeError is thrown. I'm using a try...catch statement to deal with this as shown below:
const { URL } = require('url');
try {
const absolute = new URL('https://static.pexels.com/photos/126407/pexels-photo-126407.jpeg');
console.log(absolute);
} catch (e) {
if (e instanceof TypeError) {
console.log('absolute is a relative path');
} else {
throw e;
}
}
try {
const relative = new URL('/images/picture.jpg');
console.log(relative);
} catch (e) {
if (e instanceof TypeError) {
console.log('relative is a relative path');
} else {
throw e;
}
}
Is this a legitimate use of try catch statements or am I abusing it somewhat? What's the correct way to do this if I am approaching it incorrectly?
Basically if you have a piece of code that might throw an error you should use a try catch block ... and to check whether it will throw any error you have to check the documentation.
Here as far as I know creating a URL throws an error so you have done well.
Also when you are catching an error you better log the error in a log-stream output ... it is better to log the information in a text file, also log the time,date and which part of the code is throwing the error as well.
UPDATE:
you can also write a module like URLCreator.js that handles the URL validation for you some think like this:
const {URL} = require(URL);
function createURL(givenURL, callback) {
try {
let myURL = new URL(givenURL);
callback(myURL);
} catch (e) {
if (e instanceof TypeError) {
//error handling procedure...
} else {
throw e;//cause we dont know what it is or we want to only handle TypeError
}
}
}
module.exports = createURL;
I've already saved myreferenceobject and in the sucess function, I'm attempting to run a loop and create a number of other objects save as "relations" to the refernced object.
// already have a reference to myreferenceobject
myobject.set("Name", artists_input["Name"]);
myobject.set("JbId", 12334);
myobject.save(null, {
success: function(myobject) {
console.log('New object created with objectId: ' + artist.id);
var relation = myreferenceobject.relation("Objects");
relation.add(myobject);
myreferenceobject.save();
},
error: function(myobject, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new myobject, with error code: ' + error.message);
}
});
When I run the script I get the following error
ReferenceError: parent is not defined
at ParseRelation.add
/home/myapp/node_modules/parse/lib/node/ParseRelation.js:102
return parent;
^
I followed the syntax provided by parse but I am still getting this error
Any idea?
Here is much simpler example that also fails
var TestObject = Parse.Object.extend("TestObject");
var testObject = new TestObject();
testObject.set("Name", "testName");
testObject.save(null, {
success: function(testObject) {
// Execute any logic that should take place after the object is saved.
console.log('New testObject created with objectId: ' + testObject.id);
var TestObject2 = Parse.Object.extend("TestObject2");
var testObject2 = new TestObject2();
testObject2.set("Name", "testName2");
testObject2.save(null, {
success: function(testObject2) {
// Execute any logic that should take place after the object is saved.
console.log('New testObject2 created with objectId: ' + testObject2.id);
var relation = testObject.relation("TestObjectRelation");
console.log('Make sure the relation exists ' + testObject.relation("TestObjectRelation"));
relation.add(testObject2);
testObject.save();
},
error: function(testObject2, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new testObject2, with error code: ' + error.message);
}
});
},
error: function(venue, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new testObject, with error code: ' + error.message);
}
});
Its possible that the failure isn't related to the posted code.
If testObject and testObject2 are valid, and if testObject has a column called TestObjectRelation, and that column is set up as a relation to TestObject2 class, then the OP code should work. But if any of those conditions aren't met, it will fail.
A subjective problem with the code is that it is confusingly named and structured, so it's difficult to judge by reading it whether the conditions hold and whether it does the right thing.
I can't help with the naming unless I understand the domain, but at least we can make the code structure understandable. Writing it this way will either solve the problem or allow you to discover its origin...
function createTestObjectNamed(name) {
var TestObject = Parse.Object.extend("TestObject");
var testObject = new TestObject();
testObject.set("Name", name);
return testObject.save();
}
function createTestObject2Named(name) {
var TestObject2 = Parse.Object.extend("TestObject2");
var testObject2 = new TestObject2();
testObject2.set("Name", name);
return testObject2.save();
}
function relateTestObjects(testObject, testObject2) {
var relation = testObject.relation("TestObjectRelation");
relation.add(testObject2);
return testObject.save();
}
function createAndRelateTestObjects() {
var testObject;
return createTestObjectNamed("MyName").then(function(result) {
testObject = result;
return createTestObject2Named("MyName2");
}).then(function(testObject2) {
return relateTestObjects(testObject, testObject2);
});
}
I was getting the same error and what worked was upgrading the parse library to 1.6.4
"Resolved in 1.6.4"
https://github.com/ParsePlatform/Parse-SDK-JS/issues/4
I am using node.js with mongoose. The problem i am facing is i am getting newModifier1 printed but outside that function the value is null.
Here is my code:
// Find userSchema
newModifier1 = "";
exports.findModifier = function(modifierName){
modifierModel.find({'name' : modifierName},function(err,result){
if(err){
console.log("Error : "+err);
throw err;
}
else{
newModifier1 = result;
// console.log("Modifier is searched successfully : "+newModifier1);
}
console.log("Modifier is searched successfully1 : "+newModifier1);
});
// newModifier1=temp;
return newModifier1; // it takes newModifier1 = "" value here
}
Any ideas what the problem could be?
This is what is happening:
// this is "global" an would be weirdly overwritten
// if function is called multiple times before finishing
newModifier1 = "";
exports.findModifier = function(modifierName){
// TIMESTAMP: 0
modifierModel.find({'name' : modifierName},function(err,result){
// TIMESTAMP: 2
if(err){
console.log("Error : "+err);
throw err;
}
else{
newModifier1 = result;
// console.log("Modifier is searched successfully : "+newModifier1);
}
console.log("Modifier is searched successfully1 : "+newModifier1);
});
// TIMESTAMP: 1
return newModifier1; // it takes newModifier1 = "" value here
}
I added some notes, when what is happening. As you can see and because of the async nature of node.js you return the value before you get a result back from the database.
You need familiarize yourself with the async flow and callback function.
Pass a callback function to findModifier and wait for the database to return a result.
modifierModel.find runs asynchronously and probably findModifier method is returning before the callback of find method executes. Although you see it being printed out what is returned from the method is en empty string anyway. You can use a library like async.