RESTIFY: Error: socket hang up] code: 'ECONNRESET' on multiple requests - node.js

I am implementing a node app, which brings in order details from BigCommerce.
Multiple calls are made to BigCommerce API asynchronously using Restify JsonClient.
It works fine for some calls but after that i gives error: [Error: socket hang up] code: 'ECONNRESET', sslError: undefined, body: {}
I have tried turning off socket pooling ie by setting agent=false, but it still gives same error.
Following is code which makes call to BigCommerce API
makeRequest = function (url, params, headers, orderDetails, cb) {
var options = {
headers: headers
};
var client = restify.createJsonClient({
url: url
});
client.get(options, function(err, req, res, obj) {
if(err){
console.log(err);
cb(err,obj);
} else if(obj != null) {
var result = obj;
if(orderDetails == null) {
cb(null,result);
} else {
cb(null, result , orderDetails);
}
}
});
};
I get following error:
{ [Error: socket hang up] code: 'ECONNRESET', sslError: unde
fined, body: {} } Error: socket hang up
at SecurePair.error (tls.js:993:23)
at EncryptedStream.CryptoStream._done (tls.js:689:22)
at CleartextStream.read [as _read] (tls.js:490:24)
at CleartextStream.Readable.read (_stream_readable.js:320:10)
at EncryptedStream.onCryptoStreamFinish (tls.js:301:47)
at EncryptedStream.g (events.js:175:14)
at EncryptedStream.EventEmitter.emit (events.js:117:20)
at finishMaybe (_stream_writable.js:352:12)
at endWritable (_stream_writable.js:359:3)
at EncryptedStream.Writable.end (_stream_writable.js:337:5)
at EncryptedStream.CryptoStream.end (tls.js:628:31)
at Socket.onend (_stream_readable.js:483:10)
Why am i getting such error? How can i handle it?
Thanks

I just wanted to make sure that you're setting the agent setting in the right area.
Include the
"agent": false
in your options. (It's not set in the options in the code you pasted)
Per gfpacheco in the comments here: https://github.com/restify/node-restify/issues/485
By default NodeJS uses agents to keep the TCP connection open, so you can reuse it.
The problem is that if the server is closed, or it closes your connection for whatever reason you get the ECONNRESET error.
To close the connection every time you just need to set agent: false in your client creation
I've tried this solution and it worked for me.
Other than that, the
"secureOptions": "constants.SSL_OP_NO_TLSv1_2"
solution posted here sounds like it could be the right path, since you're getting an sslError.

Maybe you are running into this issue https://github.com/joyent/node/issues/5360
TL;DR: You could try with latest node version and secureOptions: constants.SSL_OP_NO_TLSv1_2 added to your options.

Related

How to fix 'events.js :167 error Error: connect ECONNREFUSED 127.0.0.1:443' in Node.js when no other apps seems to be attempting to use the port?

I'm getting the error described below when running my node.js app after perfoming a few api calls.
The error does not always show in the exactly same place/line of code. But most of the times it is at the end of the api call.
events.js:167
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 127.0.0.1:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1113:14)
Emitted 'error' event at:
at TLSSocket.socketErrorListener (_http_client.js:391:9)
at TLSSocket.emit (events.js:182:13)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
Based on similar questions here at SO my hypothesis is that a) there is something using 127.0.0.1:443 and therefore conflicting with my app or b) node is trying to use 127.0.0.1:443 but there is nothing there for it to use (my app is listening to localhost :3000).
Hyphothesis a) doesn't seem likely since after running netstat -ano | findstr 127.0.0.1:443 nothing shows up (when app is running and right after it terminates).
Also killed every node.exe and mongod.exeb using any port in my computer, closed the terminal and restarted the node app without success.
In case error is related with hypothesis b) I'm not sure how to address it.
api.post('/parsePOpdf', wagner.invoke(function(Pdfeq, Pdfdocspec, Product, User, Order){
return async function(req,res){
//... some code
pdfParser.on("pdfParser_dataError", errData => console.error(errData.parserError) );
pdfParser.on("pdfParser_dataReady", async function(pdfData) {
fs.writeFile("./test.json", JSON.stringify(pdfData), function(err){
console.log(err);
});
let pages = pdfData.formImage.Pages;
//console.log('pages 557', pages);
let order = {
orderDetails : {
supplier : [{
item : []
}]
}
};
for (const page of pages){
let value = await getItemsInPDF(page, productKeys, pdfParsingDetails, order, Product, customer, supplierLink, User);
//... more code
order = value;
}
return res.json(order);
});
pdfParser.loadPDF(pdfFile);
}
}));
I would expect the code to finish without throwing this error.
It turns out that the problem was in the api code: an http.get line to fetch a remote file was generating the conflict. This makes sense since the error was not present for other endpoints of the api.
So learning is that if the terminal reports no app using the suspected conflicting port (see question) answser should be within the same code and you need to go line by line to identify which one is causing the problem (instead of focusing on other apps trying to use the same port, like I was focusing on).

How to track down error in node network code?

I am trying to track down why my code is failing with this error:
{ Error: connect ECONNREFUSED 127.0.0.1:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1082:14)
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 443 }
and the stack trace for that error looks like this:
Error: connect ECONNREFUSED 127.0.0.1:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1082:14)
I am making a network connection, but I am not trying to connect to localhost.
The network code I am using works just fine (and connects to the right host) in other contexts.
I'm using node 11.6.0 as supplied by brew install, and it looks like the only occurrence of the string "net.js" in the brew "Cellar" directory structure is in the node binary itself. In other words, even after
brew install --build-from-source node
running
find /usr/local/Cellar/node/11.6.0 -type f | xargs fgrep -l net.js
only finds one file: /usr/local/Cellar/node/11.6.0/bin/node and there's no net.* files in that directory tree.
If it matters, my code which seems to trigger this error looks like this:
const get_json_with_auth= async (channel, url) => {
const parsed_url= URL.parse(url);
return new Promise((good, fail) => {
let request= require('https').get({
hostname: parsed_url.hostname,
path: parsed_url.path,
headers: {
Authorization: get_auth('GET', channel, url)
}
});
console.log('url', url);
request.on('response', response=> {
const chunks= [];
response.on('data', data=> chunks.push(data));
response.on('end', ()=> good(JSON.parse(Buffer.concat(chunks).toString())));
});
request.on('error', err=> fail(err));
});
};
(I'm on OSX high sierra here.)
But, once again, the host name in the url I'm using does not resolve to localhost (and works just fine in other contexts).
How do I isolate a problem like this?
Running my code with the environmental variable NODE_DEBUG='net,tls,http,https' gave me enough information to recognize (and isolate) the problem.

NodeJS : Error: read ECONNRESET at TCP.onStreamRead (internal/stream_base_commons.js:111:27)

Using Polling like below to check if the content of the file is changed then, other two functions are called
var poll_max_date=AsyncPolling(function (end,err) { if(err) {
console.error(err); } var stmp_node_id=fs.readFileSync(path.join(__dirname,'node_id'),"utf8");
console.log("--------loaded node : "+stmp_node_id);
if(druid_stmp_node_id!=stmp_node_id) {
// MAX DATA CUT-OFF DRUID QUERY
druid_exe.max_date_query_fire();
// // DRUID QUERY FOR GLOBAL DATA
druid_exe.global_druid_query_fire();
druid_stmp_node_id=stmp_node_id; }
end(); }, 1800000).run();//30 mins
Its working fine for sometime, but then getting below error like after 4 - 5hours :
events.js:167
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:111:27) Emitted 'error' event at:
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
tried using fs.watch to monitor the changes in the file instead of polling like below :
let md5Previous = null; let fsWait = false;
fs.watch(dataSourceLogFile, (event, filename) => { if (filename) {
if (fsWait) return;
fsWait = setTimeout(() => {
fsWait = false;
}, 1000);
const md5Current = md5(fs.readFileSync(dataSourceLogFile));
if (md5Current === md5Previous) {
return;
}
md5Previous = md5Current;
console.log(`${filename} file Changed`);
// MAX DATA CUT-OFF DRUID QUERY
druid_exe.max_date_query_fire();
// DRUID QUERY FOR GLOBAL DATA
druid_exe.global_druid_query_fire(); } });
Its is also working fine for sometime, but then getting same error like after 4 - 5hours :
events.js:167 throw er; // Unhandled 'error' event ^
Error: read ECONNRESET at TCP.onStreamRead
(internal/stream_base_commons.js:111:27) Emitted 'error' event at: at
emitErrorNT (internal/streams/destroy.js:82:8) at emitErrorAndCloseNT
(internal/streams/destroy.js:50:3)
But when run in Local Machine, its working fine. the error occurs only when run in remote Linux Machine.
somebody can help me how I can fix that problem?
Use fs.watchFile once , because fs.watch is not consistent across platforms,
https://nodejs.org/docs/latest/api/fs.html#fs_fs_watchfile_filename_options_listener
Change your code according to the requirement.
It has been happening since the users are closing the browser before the data request is received, leading to Connection Reset.
Used PM2 (http://pm2.keymetrics.io/) to run the application, and it is working great now .

EPIPE write error html-pdf only on appfog server

I'm having a very weird EPIPE write error when I'm trying to generate a PDF from HTML with this module:
https://www.npmjs.com/package/html-pdf
The exact error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at errnoException (net.js:904:11)
at Object.afterWrite (net.js:720:19)
The line where I call the PDF gen:
var pdfgen = require("html-pdf");
pdfgen.create(html, options).toFile('whappbook.pdf', function(err, res) {
var errorCount = 0;
if (err) {
console.log(err);
errorCount++;
if(errorCount > 2) {
return console.log(err);
} else {
return create();
}
}
console.log(res); // { filename: '/app/businesscard.pdf' }
});
I've tried just using <h1>Testing</h1> as the HTML to see if the file was too big, but that wasn't the case.
Note: local everything works perfectly fine, but when I run this code on Appfog it doesn't work, so I suspect it has something to do with missing dependencies or file writing rights.
I'm writing directly to the home directory (in Appfog's case thats /app).
HTML-PDF is using PhantomJS and I've also directly npm'd that in my app because some people were reporting issues when it wasn't directly installed, but that didn't solve my problem either.
If there is any information that I can additionally provide please let me know!

node.js - handling TCP socket error ECONNREFUSED

I'm using node.js with socket.io to give my web page access to character data served by a TCP socket. I'm quite new to node.js.
User ----> Web Page <--(socket.io)--> node.js <--(TCP)--> TCP Server
The code is mercifully brief:
io.on('connection', function (webSocket) {
tcpConnection = net.connect(5558, 'localhost', function() {});
tcpConnection.on('error', function(error) {
webSocket.emit('error', error);
tcpConnection.close();
});
tcpConnection.on('data', function(tcpData) {
webSocket.emit('data', { data: String.fromCharCode.apply(null, new Uint8Array(tcpData))});
});
});
It all works just fine in the normal case, but I can't guarantee that the TCP server will be there all the time. When it isn't, the TCP stack returns ECONNREFUSED to node.js - this is entirely expected and I need to handle it gracefully. Currently, I see:
events.js:72
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)
... and the whole process ends.
I've done a lot of searching for solutions to this; most hits seem to be from programmers asking why ECONNREFUSED is received in the first place - and the advice is simply to make sure that the TCP server is available. No discussing of handling failure cases.
This post - Node.js connectListener still called on socket error - suggests adding a handler for the 'error' event as I've done in the code above. This is exactly how I would like it to work ... except it doesn't (for me), my program does not trap ECONNREFUSED.
I've tried to RTFM, and the node.js docs at http://nodejs.org/api/net.html#net_event_error_1 suggest that there is indeed an 'error' event - but give little clue how to use it.
Answers to other similar SO posts (such as Node.js Error: connect ECONNREFUSED ) advise a global uncaught exception handler, but this seems like a poor solution to me. This is not my program throwing an exception due to bad code, it's working fine - it's supposed to be handling external failures as it's designed to.
So
Am I approaching this in the right way? (happy to admit this is a newbie error)
Is it possible to do what I want to do, and if so, how?
Oh, and:
$ node -v
v0.10.31
I ran the following code:
var net = require('net');
var client = net.connect(5558, 'localhost', function() {
console.log("bla");
});
client.on('error', function(ex) {
console.log("handled error");
console.log(ex);
});
As I do not have 5558 open, the output was:
$ node test.js
handled error
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' }
This proves that the error gets handled just fine... suggesting that the error is happening else-where.
As discussed in another answer, the problem is actually this line:
webSocket.emit('error', error);
The 'error' event is special and needs to be handled somewhere (if it isn't, the process ends).
Simply renaming the event to 'problem' or 'warning' results in the whole error object being transmitted back through the socket.io socket up to the web page:
webSocket.emit('warning', error);
The only way I found to fix this is wrapping the net stuff in a domain:
const domain = require('domain');
const net = require('net');
const d = domain.create();
d.on('error', (domainErr) => {
console.log(domainErr.message);
});
d.run(() => {
const client = net.createConnection(options, () => {
client.on('error', (err) => {
throw err;
});
client.write(...);
client.on('data', (data) => {
...
});
});
});
The domain error captures error conditions which arise before the net client has been created, such as an invalid host.
See also: https://nodejs.org/api/domain.html

Resources