here's a snippet of my code
console.log("IS RESTCLIENT UNDEFINED?");
console.log(restClient === undefined);
console.log(restClient);
restClient.get(options, function(resterr, restreq, restres, restobj) {
assert.ifError(resterr);
//not important
return next();
});
The problem is that when it gets executed (it's basically most of the handler for a route, simple stuff, nothing esoteric) the output is as following:
IS RESTCLIENT UNDEFINED?
false
JsonClient {<a lot of stuff describing the client>}
assert.js:327
assert.ifError = function(err) { if (err) throw err; };
^
InternalError: restClient is not defined
at parseResponse (/srv/oms-profiles-module/node_modules/restify/lib/clients/json_client.js:67:23)
at IncomingMessage.done (/srv/oms-profiles-module/node_modules/restify/lib/clients/string_client.js:151:17)
at IncomingMessage.g (events.js:260:16)
at emitNone (events.js:72:20)
at IncomingMessage.emit (events.js:166:7)
at endReadableNT (_stream_readable.js:893:12)
at doNTCallback2 (node.js:430:9)
at process._tickCallback (node.js:344:17)
The client is defined at the beginning of the file "as usual" (worked until now), and it uses the npm module restify. I don't even understand if the problem could be the scoping or what else, has anybody gotten any good advice on where I could bang my head on?
Thanks
UPDATE: this is not a problem with scopes and such, I presume; I suspect it is something with restify because otherwise the error would be something like "ReferenceError: restClient is not defined". Still, I am at a loss since it was working before and I did not introduce any major change for it to break. Restify version is 3.0.3
Alright, the answer is simple and I feel stupid (as I should),
the assert was being fired as there is a resterr. It comes from the API handler that is being called with restClient.get()
However I was expecting the whole (other) program to do something like crash (on another assert) or to tell me ReferenceError: restClient is not defined, but analysing the logs it did NOT happen. Thus I thought that the problem was in the snippet up here and not in the remote API that I was calling (still coded by me).
Related
I have a nodeJS application (server) and using some 3rd party npm modules.
Also in my application, I have the following code:
process.on("unhandledRejection", (reason, promise) => {
console.error(`Unhandled Rejection at: ${promise} reason: ${reason}`);
restartApp(); // ← Is this a must action?
});
Seems like not all the promises are rejected properly, in the 3rd party modules and maybe also in my code.
I know it's the last resource to use this event handler.
Question after catching this unhandle rejection event, do I need to restart my application?
It's useful to divide errors into two broad categories: Operational and Programmer errors.
Operational errors are (unavoidable) run-time problems experienced by correctly-written programs, such as disk full, network connection loss etc.
Programmer errors are caused by bugs or oversights in code, that can not be handled since they will cause the program to enter an unknown state, they could be in your code or a module you're calling.
Best practice for programmer errors is to crash immediately. You should run your programs using a restarter (see below) that will automatically restart the program in the event of a crash. With a restarter in place, crashing is the fastest way to restore reliable service in the face of a transient programmer error.
If the error is an operational error, it may make sense to try to recover or re-try the operation (if this makes sense). There's no point retrying a REST request if you're getting 400 errors for example, but there might be if you're getting 500 errors (the system may recover).
See more here in this very useful guide:
https://www.joyent.com/node-js/production/design/errors
In your specific case, you're handling an unhandledRejection, this means that an application is in an undefined state... very similar to an unhandledException, the best thing to do is clean up anything that needs to be done and then exit or restart, also log the error (this is super important!, is the error happening every day, hour or minute?)
I'd suggest using a process monitor such as PM2 or Forever. These can auto-restart when you exit due to an error, and do lots of other cool stuff like logging these events.
Here's another nice guide from Heroku on the same topic:
https://blog.heroku.com/best-practices-nodejs-errors
The blogger (Julián Duque) has even put together some best practice on handling these events:
https://blog.heroku.com/best-practices-nodejs-errors#putting-it-all-together
This looks a little like so:
const http = require('http')
const terminate = require('./terminate')
const server = http.createServer(...)
const exitHandler = terminate(server, {
coredump: false,
timeout: 500
})
process.on('uncaughtException', exitHandler(1, 'Unexpected Error'))
process.on('unhandledRejection', exitHandler(1, 'Unhandled Promise'))
process.on('SIGTERM', exitHandler(0, 'SIGTERM'))
process.on('SIGINT', exitHandler(0, 'SIGINT'))
The Terminate module:
function terminate (server, options = { coredump: false, timeout: 500 }) {
// Exit function
const exit = code => {
options.coredump ? process.abort() : process.exit(code)
}
return (code, reason) => (err, promise) => {
if (err && err instanceof Error) {
// Log error information, use a proper logging library here :)
console.log(err.message, err.stack)
}
// Attempt a graceful shutdown
server.close(exit)
setTimeout(exit, options.timeout).unref()
}
}
module.exports = terminate
I think this style of managed, centralized handling of these events is the right way to go.
I'm working on a discord bot that does a variety of things. It keeps randomly crashing and I tracked down the source of the error. What it does is it downloads images sent to it in a discord private message, hashes them and sets their name to the hash to make sure no duplicates exist. This is not the most efficient way to do so but it works.
Here's my code (it's a bit messy)
message.attachments.forEach(url => {
if (!message.author.bot) {
function getDate() {
let d = new Date().getTime();
return d;
}
tempdate = new getDate();
ext = path.extname(url.url);
request.get(url).on(`error`, console.error).pipe(fs.createWriteStream(`./temp/Img-${tempdate}${ext}`));
hash = sha256(`./temp/Img-${tempdate}${ext}`);
if (fs.existsSync(`./attachments/Img-${hash}${ext}`)) {
request.get(url).on(`error`, console.error).pipe(fs.createWriteStream(`./attachments/Img-${hash}${ext}`));
console.log(`Error: Duplicate File`)
}
fs.createWriteStream(`./attachments/Img-${hash}${ext}`);
console.log(`Wrote Hashed File.`)
fs.unlinkSync(`./temp/Img-${tempdate}${ext}`)
}
})
Every once in a while, however it returns this:
fs.js:1061
return binding.unlink(pathModule._makeLong(path));
^
Error: ENOENT: no such file or directory, unlink 'C:\Users\xxxxx\Desktop\testbot\temp\Img-[object Object].png'
at Object.fs.unlinkSync (fs.js:1061:18)
at Client.client.on.message (C:\Users\xxxxx\Desktop\testbot\yes.js:48:20)
at emitOne (events.js:116:13)
at Client.emit (events.js:211:7)
at MessageCreateHandler.handle (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\packets\handlers\MessageCreate.js:9:34)
at WebSocketPacketManager.handle (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\packets\WebSocketPacketManager.js:103:65)
at WebSocketConnection.onPacket (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:333:35)
at WebSocketConnection.onMessage (C:\Users\xxxxx\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:296:17)
at WebSocket.onMessage (C:\Users\xxxxx\node_modules\ws\lib\event-target.js:120:16)
at emitOne (events.js:116:13)
I assume I did something wrong here. I can't find any answers online
You are mixing synchronous and asynchronous code.
The .pipe() is absolutely asynchronous, yet you're trying to assume that it's done immediately. You can't reliably program this way.
You need to listen for an event to know when the .pipe() is done before you can proceed with the rest of the processing.
And, as soon as you make it event driven, your .forEach() will run ahead with multiple iterations trying to run at the same time and then the fact that your variables aren't declared locally inside the loop will cause variable conflicts.
Also, what is this line of code doing all by itself:
fs.createWriteStream(`./attachments/Img-${hash}${ext}`);
You create a write stream, but don't even keep track of it. That will just leak a file handle.
As for solutions, it really requires a significant rewrite. I've answered a similar question here Issue with request and .pipe(). In that answer, I created a promise wrapper for .pipe() which would then let you use await to sequence a pipe operation. I'd probably use that solution in rewriting this code.
I'm somewhat new to javascript, but I wanted to try to understand how stack-tracing works in nodejs. I was a little lazy to look at the source code, so I just consulted the language reference https://www.ecma-international.org/ecma-262/10.0/index.html#sec-runtime-semantics-catchclauseevaluation and tried to see what works. So, here is the mystery: in the repl I get some odd results when catching and throwing.
When I run:
try { throw Error('foo'); } catch (e) { throw e; }
I get as output:
Error: foo
But when I run:
try { throw Error('foo'); } catch (e) { console.log(e); throw e; }
I get as output:
Error: foo
at repl:1:13
at ContextifyScript.Script.runInThisContext (vm.js:50:33)
at REPLServer.defaultEval (repl.js:240:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:468:10)
at emitOne (events.js:121:20)
at REPLServer.emit (events.js:211:7)
at REPLServer.Interface._onLine (readline.js:282:10)
at REPLServer.Interface._line (readline.js:631:8)
Error: foo
at repl:1:13
at ContextifyScript.Script.runInThisContext (vm.js:50:33)
at REPLServer.defaultEval (repl.js:240:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:468:10)
at emitOne (events.js:121:20)
at REPLServer.emit (events.js:211:7)
at REPLServer.Interface._onLine (readline.js:282:10)
at REPLServer.Interface._line (readline.js:631:8)
It seems as though calling console.log(e) causes the error object to trace the execution context stack (I hope I'm using this term correctly), but if it passes through to the repl without the context.log(e) it only knows about its error message.
I've tried different permutations of this and also nesting in different lexical contexts (functions and another try-catch block), and they all seem to give this "funny" behavior. Also, when executing these as scripts I always get an expected error message and stack-trace, so I'm led to believe that the implementation of the repl is at fault here. However, before diving into the source, I wanted to probe some experts to see if there is some good reason for this behavior, or if it is just a stupid corner case that I've come up with.
Well, I don't know if it's kosher to answer my own question, but I dug into the nodejs source and found out what the deal is. I tracked it down to repl.js: line 404. Here there is a call to script.runInThisContext. At this point, the line throw new Error() "escapes" the repl and ends up getting caught a few lines below. Here, there is check for process.domain, which apparently succeeds in the repl, but not in a script context. This then emits a domain error, which doesn't do much. If you go to self._domain.on('error',... you will see that all the stack tracing stuff is taken care of here.
I actually added a line self._domain.emit('error'... to the source right before the process.domain.emit('error',... call, and it then printed out a nice stack trace for me, so I'll write the guys over at nodejs and see if it is something they would like to fix. There may be a very good reason not to do so, I didn't look into it in that great of detail.
At this point I'm reminded of a scene from Burn after Reading. Watch it if you have a dry sense of humor: https://www.youtube.com/watch?v=46h7oP9eiBk
I'm trying to run a sample code from Github to insert the data in fire store database but I am getting an error.
Here is the error:
21:1 error Expected catch() or return promise/catch-or-return
21:35 error Each then() should return a value or throw promise/always-return a value or throw
Here is the code where I am getting the error:
// getting data
db.collection('cafes').get().then((snapshot) => { //----line 21
snapshot.docs.forEach(doc => {
renderCafe(doc);
})
});
Those look like lint warnings, not actual JS errors unless you're running this in some non-standard environment.
The first one appears to be telling you that you have no .catch() to handle errors from your db .get(). That's good advice. You must handle errors.
The second one appears to be wrong. There's no rule that you have to return a value from a .then(). If it's the end of the chain and you're done with the processing, there's no reason to return anything. You can probably make the second warning go away by putting a return 0 after renderCafe(doc), though personally I'd either stop using a tool that gives such bad advice or configure it not to warn on this issue because it's wrong and adding dummy, non-functional code just to make some tool be happy is not something I recommend.
I've got quite a big library written in node.js, too big to paste here (>20 files). I've got a try..catch that catches the error, I debug the catch part and I console.log the error as below:
{ [ParseError: value.key.split is not a function]
message: 'value.key.split is not a function',
path: [ 'properties', 'statement1' ],
name: 'ParseError' }
The thing is - I don't know which file is that and I'm somehow unable to debug it. Can I access the source file (line, preferably) where this error was thrown? What node.js returns is the actual line that it tried to execute, but I can hardly spot where it is... Any suggestions would be welcome.
Try
console.dir( error );
on error instead. You also might try logging the stack property explicitly:
console.log( error.stack );