How to catch node TimeoutError and log the request? - node.js

I'm writing an application in node in which I do many websocket requests to a remote service (using the ws library). So the remote service is the server, and my node application is the client. It works quite well, but occasionally I suddenly get a long list of the following TimeoutError:
Unhandled rejection TimeoutError: ResourceRequest timed out
at ResourceRequest._fireTimeout (/Users/kramer65/repos/mmj/node_modules/generic-pool/lib/ResourceRequest.js:58:17)
at Timeout.bound (/Users/kramer65/repos/mmj/node_modules/generic-pool/lib/ResourceRequest.js:8:15)
at ontimeout (timers.js:386:11)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
Since I do many different websocket calls I now wonder for which call this error occurs. I tried wrapping the ws.send() in a try/catch as I pasted below, but that doesn't seem to do anything.
try {
ws.send(request_json);
} catch(e) {
console.log('WEBSOCKET ERROR', e);
console.log('WEBSOCKET JSON', request_json);
}
Does anybody know how I can catch the TimeoutError and log the request contents? All tips are welcome!
[EDIT]
As suggested by #Mark_M I added a callback to the ws.send() method as follows:
ws.send(JSON.stringify(request_obj)), (error)=>{
console.log('WEBSOCKET ERROR', request_obj.action, error);
});
Unfortunately I still get the same errors as I posted on the top of this question.
[EDIT2]
I also tried the suggestion made by #wrangler:
ws.send(JSON.stringify(request_obj));
ws.onerror = function(event) {
console.log('WEBSOCKET ONERROR', request_obj.action, event);
};
ws.onclose = function (event){
console.log('WEBSOCKET ONCLOSE', request_obj.action, event);
};
but unfortunately this also doesn't seem to work. I still get the same errors as I posted on the top of this question.
Any other ideas?

The ws.library send() method takes an optional callback that will be called when it encounters an error. You can catch those errors with:
ws.send('something', function ack(error) {
if(error) //handle error
}
Try/catch will catch immediate errors, but, as you noticed, it doesn't help with async errors.
Alternatively, it looks like you are calling send() within some other async code (because you aren't just getting an error, you're getting an unhandled promise rejection). You could add a .catch() onto that promise if it's in your own code.

You can use onerror callback of websocket object for receiving any error.
Example:
var exampleSocket = new WebSocket("ws://echo.websocket.org");
exampleSocket.onopen = function (event) {
console.log("open");
exampleSocket.send("hellow world");
};
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
exampleSocket.onerror=function(event){
console.log("Error");
}
Link:http://jsfiddle.net/g28yuymv/1/
Link2:http://jsfiddle.net/g28yuymv/10/

Ok, stupid me. After looking at the initial error a bit better I found that it was an error in the generic-pool package. On its npm page it says it's
a Promise based API, which can be used to reuse or throttle usage of
expensive resources such as database connections
The problem turned out to be my database connection (which is used extensively). I solved it using this tip on github, which suggests to set the sequelize init pool settings as follows:
pool: {max: 5, min: 0, idle: 20000, acquire: 20000}
That solved it for me.
Thanks to the answers, I now have proper websocket error reporting though.. :-)

Related

io.connect() is not working and i can't figure what is the problem

[and this is the angular code ][1] this is my node js code
Please copy/paste your actual code. Screenshots are discouraged on SO.
Be sure to include ERROR HANDLING in all of your I/O operations. For example:
https://socket.io/docs/v4/client-initialization/
socket.on("connect_error", (err) => {
if (err.message === "invalid credentials") {
socket.auth.token = "efgh";
socket.connect();
}
});
... or ...
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onerror
webSocket.onerror = function(event) {
console.error("WebSocket error observed:", event);
};
Your next step is to get a viable error message.
Please review the library's documentation to determine the "best" way to catch and handle errors for your particular application.

UnhandledPromiseRejectionWarning Persists Even After Chaining a .catch()

My system consists of an Angular UI and a Node API. The UI submits a file to the API for processing, then gets the result back. This all works - however - the API sometimes fails at processing unexpected data.
I want to be able to catch the error(s) when they arise, stop execution so they won't screw up the UI, then send a message back to UI.
Here is my code so far:
const IncomingForm = require('formidable').IncomingForm;
asynch function myApi(req, res)
{
try // (1)
{
var form = new IncomingForm(...);
form.on('file', async(field, file) =>
{
const [result] = await sometimesBad(inParam); // (2) attach .catch(...);
...
res.send({goodFinal}); // execution should not reach here if error occurs before
});
form.on('end', ()=> {})
form.parse(req)
}
catch (erApi) // (3)
{
... // (4)
}
}
async function sometimesBad(x)
{
try // (5)
{
... lines of code could have run-time error depends on x ...
return goodResult;
}
catch(err2) // (6)
{
... // (7)
}
}
Currently, after hours of searching and trial and error, I:
am able to send a message back by chaining a .catch() at (2)
am unable to stop the execution via any combination of (1), (3), (4), (5), (6), (7), including the use of next(), throw new Error(), await Promise.reject(), return Promise.reject().
am always getting UnhandledPromiseRejectionWarning: Unhandled promise rejection.
Node version: 14.9
Update: In addition to accepted answer, there is no need to have (5), (6), (7).
In your code if (2) throws the error indeed is not handled. To handle it, you need to wrap the code inside async (field, file) => ... into try / catch, similar to how you did on the top level of middleware, and inside the catch you do next(error). Also add default error handler after all routes in your app. See How to return error to the client client without making node server crash? regarding that.
You can stop unhandledRejection(s) from crashing your app by handling them. However, if you fail to handle them using catch blocks, you can also watch for events on the process.
Code Example from the Docs:
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', promise, 'reason:', reason);
// Application specific logging, throwing an error, or other logic here
});
somePromise.then((res) => {
return reportToUser(JSON.pasre(res)); // Note the typo (`pasre`)
}); // No `.catch()` or `.then()`
Alternatively, you can make your sometimesBad function return a Promise, which would cause all errors happening inside the Promise body to be thrown, which can then be handled in the catch block of the caller.

NodeJS : prevent application to crash on error

When an error occurs in NodeJS application, the server may crash and stop if an exception occurs.
How can I prevent this situation so that the server never stops on error, but returns and error code instead ?
--
EDIT
Here is a method which causes a server crash (table foo doesn't exist) :
app.get('/articles/list', function(req, res) {
connection.query('select * from foo', function(err, rows, fields) {
if (err) throw err;
res.send(JSON.stringify(rows));
});
});
-- BEST SOLUTION
Finally, I found the best solution for me :
http://rowanmanning.com/posts/node-cluster-and-express/
In summary, it consists in using a cluster of server, and to restart a server when it exits
If you are using express, you can use this
function clientErrorHandler (err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' })
} else {
next(err)
}
}
app.use(clientErrorHandler);
I suggest you to ready this article, it will clarify a lot for you.
JFK, be aware of async error catching, most common error, once you have async stuff which is wrapped in try-catch.
Also, avoid usage of
process.on("uncaughException", () => {....})
This is quite bad, because when an uncaught exception is thrown you can’t reliably continue your program at this point.Let it fail and restart with daemonizer's like pm2, forever and etc.
As general rule, you should handle all errors and promise rejects in your code to avoid uncaught Exceptions.
For errors: using try-catch statement
For promises: using .catch method
Btw Node permits you to intercept an uncaughtExceptions or unhandledRejection events, but is not a good practice to handle errors at this level and prevent program exits, because can generate unpredictable behaviours.
Use try catch... for parts of code, which throws exception
try{
//youre code here
}catch(error){
console.log(error)
}

how to avoid promise rejection when firing 'error' event with EventEmitter in nodejs?

I have code that looks like
var EventEmitter = require('events');
class MyClass extends EventEmitter{
doSomething(){
this.emit('error', new Error('this is why') );
}
}
function doSomethingAsync(){
return new Promise( (resolve,reject) =>{
new MyClass().doSomething();
resolve();
});
}
process.on('unhandledRejection', function(reason){
console.error('unhandled rejection', reason, reason.stack);
});
setTimeout( doSomethingAsync,1);
If I don't assign an error event handler with myClass.on('error', ()=>{ ... }) the unhandledRejection handler is triggered when the error event is thrown and doSomething flow is interrupted (I don't see the after print)
if I add a handler, everything works fine (I do see the after print).
How can I avoid this? Why should an 'error' event cause a promise rejection?
sometimes I don't care if an event emitter throws an error event. but I will always care if a promise failed.
is this wrong? should I treat them the same?
using nodejs 4.2.1
Edit
Ok, so I learned that node treats unhandled 'error' in a special way, and if unhandled it will throw an exception.
https://strongloop.com/strongblog/robust-node-applications-error-handling/
is there a way around it? I don't see why this choice of implementation in nodejs is correct.
shouldn't there be a global handler like unhandledErrorEvent instead? like they added to unhandledRejection?
I agree, that is very annoying and I am gonna investigate that further in Node core.
In the meanwhile you can check for listeners with emitter.listeners(name), which is actually nice enough.
if (this.listeners('error').length > 0) this.emit('error', err)
I find your question to be a very good catch.

How to debug a socket hang up error in NodeJS?

I am getting the following error:
events.js:48
throw arguments[1]; // Unhandled 'error' event
^
Error: socket hang up
at createHangUpError (http.js:1091:15)
at Socket.onend (http.js:1154:27)
at TCP.onread (net.js:363:26)
In node v0.6.6, my code has multiple http.request and .get calls.
Please suggest ways to track what causes the socket hang up, and on which request/call it is.
Thank you
Quick and dirty solution for development:
Use longjohn, you get long stack traces that will contain the async operations.
Clean and correct solution:
Technically, in node, whenever you emit an 'error' event and no one listens to it, it will throw. To make it not throw, put a listener on it and handle it yourself. That way you can log the error with more information.
To have one listener for a group of calls you can use domains and also catch other errors on runtime. Make sure each async operation related to http(Server/Client) is in different domain context comparing to the other parts of the code, the domain will automatically listen to the error events and will propagate it to its own handler. So you only listen to that handler and get the error data. You also get more information for free.(Domains are depreceated).
As Mike suggested you can also set NODE_DEBUG=net or use strace. They both provide you what is node doing internally.
Additionally, you can set the NODE_DEBUG environment variable to net to get information about what all the sockets are doing. This way you can isolate which remote resource is resetting the connection.
In addition to ftft1885's answer
http.get(url, function(res)
{
var bodyChunks = [];
res.on('data', function(chunk)
{
// Store data chunks in an array
bodyChunks.push(chunk);
}).on('error', function(e)
{
// Call callback function with the error object which comes from the response
callback(e, null);
}).on('end', function()
{
// Call callback function with the concatenated chunks parsed as a JSON object (for example)
callback(null, JSON.parse(Buffer.concat(bodyChunks)));
});
}).on('error', function(e) {
// Call callback function with the error object which comes from the request
callback(e, null);
});
When I had this "socket hang up" error, it was because I wasn't catching the requests errors.
The callback function could be anything; it all depends on the needs of your application. Here's an exemple of a callback logging data with console.log and logging errors with console.error:
function callback(error, data) {
if (error) {
console.error('Something went wrong!');
console.error(error);
}
else {
console.log('All went fine.');
console.log(data);
}
}
use
req.on('error',function(err){})
Most probably your server socket connection was somehow closed before all http.ServerResponse objects have ended. Make sure that you have stopped all incoming requests before doing something with incoming connections (incomming connection is something different than incoming HTTP request).

Resources