Nodejs v0.10.x (freebsd) "X509_STORE_add_cert:cert already in hash table"

I'm work with async web api and have a problem in nodejs version higer than v0.8.9

$ uname -a FreeBSD home 9.1-STABLE FreeBSD 9.1-STABLE #0: Fri Feb 1 10:38:27 EET 2013 root@home:/usr/obj/usr/src/sys/HOME amd64

$ node -v v0.10.0

$ node ./client.js

    events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: 34401711104:error:0B07C065:x509 certificate routines:X509_STORE_add_cert:cert already in hash table:../deps/openssl/openssl/crypto/x509/x509_lu.c:357:
34401711104:error:0B07C065:x509 certificate routines:X509_STORE_add_cert:cert already in hash table:../deps/openssl/openssl/crypto/x509/x509_lu.c:357:

    at SlabBuffer.use (tls.js:221:18)
    at CleartextStream.read [as _read] (tls.js:408:29)
    at CleartextStream.Readable.read (_stream_readable.js:293:10)
    at tls.js:465:12
    at process._tickCallback (node.js:415:13)

Code (client.js):

var fs = require('fs');
var https = require('https');
var agent = require('agent').agent;

var config={
    host:           'sample.host.com',
    port:           443,
    path:           '/worker.do',
    pfx:            fs.readFileSync('./client.pfx'),
    passphrase:     "passwordHere"
};

config.agent = new https.Agent({
    pfx: config.pfx,
    passphrase: config.passphrase
});

agent.config=config;

agent.makeRequest([{request:"search",query:"*"}],function(data){
    if(!data.success){
        console.log(data.error);
        return;
    }

    var items=[];

    for(var item in data.data){
        items.push(data.data[item][0]);
    }

    agent.makeRequest([{"request":"update","group":true,"arr":JSON.stringify(items)}],function(data){
        if(!data.success){
            console.log(data.error);
            return;
        }

        console.log('Done: '+data.result);
    });

}); 

Code (agent.js):

var https = require('https');

var agent={
    config: {},
    getId: function() {
        return this.id || (this.id = new Date().getTime());
    },
    makeRequest: function(params,callback){
        var options = {
            host: this.config.host,
            port: this.config.port,
            path: '/worker.do',
            method: 'POST',
            agent: this.config.agent
        };

        var that=this;
        var req = https.request(options, function(res) {
            if(res.statusCode!='200'){
                callback({
                    success:    false,
                    error:      res.statusCode
                });
                return;
            }

            var body='';
            res.on('data', function(data) {
                body+=data.toString();
            });

            res.on('end', function(){
                try {
                    body=JSON.parse(body);
                } catch(e) {
                    callback({
                        success:    false,
                        error:      '[makeRequest] Cant parse body: '+body
                    });
                }

                var reqId=body[0];
                that.getContent(reqId,callback);
            });
        });

        req.on('error', function(e) {
            callback({
                success:    false,
                error:      e
            });
        });

        req.end(JSON.stringify(params)+'\n\n');
    },

    getContent: function(reqId,callback){
        var options = {
            path: '/worker.do?_dc='+this.getId(),
            method: 'GET',
            host: this.config.host,
            port: this.config.port,
            agent: this.config.agent
        };

        var req = https.request(options, function(res) {
            if(res.statusCode!='200'){
                callback({
                    success:    false,
                    error:      res.statusCode
                });
                return;
            }

            var body='';
            res.on('data', function(data) {
                body+=data.toString();
            });

            res.on('end', function(){
                try {
                    body=JSON.parse(body);
                } catch(e) {
                    callback({
                        success:    false,
                        error:      '[getContent] Cant parse body: '+body
                    });
                }           

                callback(body[reqId]);
            });
        });

        req.on('error', function(e) {
            callback({
                success:    false,
                error:      e
            });
        });

        req.end();

    }
}

exports.agent=agent;

On nodejs v0.6.x and v0.8.x it works perfect. On v0.10.x -- fail. Please help to find the problem.

The first request is good, but the second got this error.

The solution is to isolate your PEMs and add them back one by one, not as a bundle. At the lowest leaf, then the parent, then the parent, etc and test each time.

See https://github.com/iojs/io.js/issues/712

I'm thinking this must be a bug in the internals of node.js / io.js where duplicate certs aren't checked the very first time they're used.

What's odd is that adding a cert to the chain for a specific https server instance can cause an unrelated https request (which should be using the default chain, not anything to do with the https server).