Exception in Node server that uses http module - node.js

Please note that the above "possible answer" questions does not contain an answer to my question. I am using require("http"). In that question the person is taking a socket input variable that they can put a handler on. I do not have the same variable.
I have a very simple server that I have written in Node.
var http = require("http");
var sys = require("sys");
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({
target: "someServer"
});
http.createServer(function(request, response) {
try {
proxy.web(request,response);
} catch (err) {
sys.puts("I caught an error!");
}
}).listen(5000);
When I leave my app running, it crashes. My command line says:
events.js:72
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at errnoException (net.js:900:11)
at TCP.onread (net.js:555:19)
It seems to crash not when server is serving files, but when it is waiting for a long time between requests.
While my code is a little more complex, I do have error catching on every callback.
Why is it crashing? What can I do?

In node, sprinkling try and catch everywhere is not the same as catching every error. (And in most cases, doing so is useless.) Asynchronous operations cannot throw useful exceptions because control long ago left the block of code that invoked the operation.
Instead, many objects emit an error event. The error event is a special case in that node will throw a "real" exception if there are no listeners for the event. Because this exception is thrown from code you do not and cannot control (ie wrap with try/catch), it goes uncaught and the process ends.
So if you do not add an error listener to sockets, a socket error will bring down the entire app.
However, your unhandled error is not coming from your http requests. The http module adds an error handler to every socket automatically, and re-emits the error as a clientError event on the Server. Because EventEmitters only throw when the event is named error, the fact that you don't handle clientError does not matter.
If we read http-proxy's documentation, we see that it also throws an error event, and you aren't listening for it. Thus, your app dies whenever there's an error fetching something from an upstream server.
Add an error handler.
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong.');
console.error(err);
});
Any time you see this error ("// Unhandled 'error' event"), it means you need to find out what is emitting an error event and add a listener to handle the error.

Related

Meteor - How to handle external API connection errors?

I'm using a few external API's (some in timers, every minute or so) and sometimes I get some connection errors because of network problems or because the external systems are down for some reason. When I get this errors, the app restarts, and if the error persists the app continues restarting.
Any ideas on how can I ignore the connection error and keep the app running?
Code Example:
try {
var req = https.request(options, callback);
req.write(JSON.stringify(params));
req.end();
} catch (e) {
throw e;
}
Based on your code example. You're doing throw e inside your try catch. Essentially, you're catching an error and then throwing the error. Just do console.error(err) or however you want to handle that error, without throwing. This is what will cause your instance to stop.

catching exceptions in node.js express proxy application

I have some proxy code like this below. Problem is that whenever the target server is down, this code fails to capture the error, resulting in the entire application crashing with Error: connect ECONNREFUSED.
For a proxy server, this is terrible, it needs to just return an error to the caller, not crash altogether upon the first time that the target server is unreachable.
What is the right way around it these days?
Node version 6.
let targetUrl = "http://foo.com/bar"
app.options('/cors-proxy/bar', cors())
app.post('/cors-proxy/bar', function(req, res) {
console.log(`received message with method ${req.method} and some body ${req.body}`)
console.log(`relaying message to ${targetUrl}`)
try {
req.pipe(
request({
url: targetUrl,
method: req.method,
json: req.body
})
).pipe(res);
} catch (err) {
res.status(502)
res.render('error', {
message: err.message,
error: err
});
}
});
Thanks!
In general, you can't use try/catch to catch exceptions that may occur in asynchronous callbacks or asynchronous operations. That will only catch synchronous errors.
Instead, you have to read how each particular asynchronous operation reports errors and make sure you are plugged into that particular mechanism.
For example, streams report errors with a message to the stream that you intercept with stream.on('error', ...). For example, a request() can report errors several different ways depending upon which request() library you are actually using and how you are using it.
Some references:
Error handling with node.js streams
Stream Readable Error
How Error Events Affect Piped Streams in Node.js

How to catch a global error with NodeJS

I am getting an unhandled error but not sure where it's coming from. My app has several http.request(options, callback).end() in different methods, with the callback's trapping "uncaughtException" and "error". I'd like to know which of my methods initiated this issue. Below is the error I get. It is random. Any ideas how to track this down? I was hoping for some global way of trapping unhandled errors.
events.js:85
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at exports._errnoException (util.js:746:11)
at TCP.onread (net.js:559:26)
ECONNRESET means that the other side of the TCP connection is aborted. You could look at the server logs, but since it was random times this makes me think that the server becomes overloaded and kills a few connections.
If you're starting a process at any point in the process try the below:
process.on('uncaughtException', function (err) {
console.error(err.stack);
console.log("Node NOT Exiting...");
});
attach a
request.on('error', function(err) {
// Handle error
});
to your requests.
You can also catch uncaught errors for the process:
process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err);
});
This error as it reads states the connection was reset, so its definitely one of the requests.

uncaughtException not catching thrown Errors

I'm working on an api in Node.js and learned about an option to give my errors one last look before crashing my app...(uncaughtException)
Note: I'm well read at this point on all the reasons some people don't like this feature, so please don't post those concerns here.
The problem I'm experiencing is this:
I create custom error classes for different pieces of code. for instance a Redis_Exception, which will get thrown in response to errors in my cache layer.
However the following does not bubble up to my uncaughtException function:
throw new Redis_Exception('Some error here');
Instead my app simply prints Redis_Exception: Some error here to the console. No stack trace as per usual.
Is there some reason that errors thrown in this manner would not bubble up to the top of my applications process?
An easier way around it, add a middleware with your express server with 4 arguments, 1st argument being the error. This will override the finalhandler handler.
app.use((err, req, res, next) => {
// Similar to uncaughtException handler
// Log error, maybe send it to central server
// Send Custom Log message maybe?
return res.send('Nice server error to user');
}
You should also still keep process.on('uncaughtException', fn); to handle any uncaught exceptions outside of the http request response pipeline.
Figured out what it is. For some reason express has decided to handle my errors for me.
In this file /node_modules/finalhandler/index.js on line 67 they basically handle any unhandled errors, which keeps uncaughtErrors from bubbling up to the top of the stack...or down to the bottom. Not really sure which direction this thing is facing.. :D
I added a line to that file and errors starting going through to my exception handler:
66 // unhandled error
67 if (err) {
68 throw err; //my line
I'm not sure how i'm going to move forward knowing this as I don't want to overwrite core functionality, but I'm armed with knowledge now.
UPDATE: After opening tickets with finalhandler and express I got back some info on how to override the default functionality.
The tickets I opened are:
https://github.com/pillarjs/finalhandler/issues/6
https://github.com/strongloop/express/issues/2707
Basically if you wrap your app object in a new http server you can override the last event with your own final function.
var express = require('express')
var http = require('http')
var app = express()
// declare things on app
var server = http.createServer(function (req, res) {
app(req, res, function (err) {
// this is your replacement for finalhandler
})
})
server.listen(3000)

Debugging in node.js

I build a server which get many requests and response to them.
In some cases, there is an error which cause the server to crush:
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, open '/mnt/ace/0/file'
I have two problems:
the stack trace doesn't give me any information about the line in my application that cause this exception (I can't do manually debugging because it happens just when I get 1000 request or more).
I don't want that my server ould crush. I prefer that it will raise an exception, but will continue to work.
What the best implementation for this?
You can listen for that kind of stuff and not have it crash the app, but that's not always a great idea.
process.on('uncaughtException', function(err) {
console.log('Something bad happened');
console.log(err.stack);
});
In your case, have you tried checking ulimit settings? You may be having problems opening file handles under loads of 1000+.
Another way of thinking about this is to use domains (if you're using >= 0.8). Domains give you a finer grain of control over how you handle errors based on what contexts cause them.
var domain = require('domain').create();
domain.on('error', function(err) {
console.log(err);
});
domain.run(function() {
// Your code that might throw
});

Resources