The remote server rejected the SSL/TLS certificate presented by your Node.js application during the handshake. This occurs when the certificate is invalid, self-signed, or the certificate chain is incomplete.
This error occurs when Node.js initiates an HTTPS connection to a remote server, and the server rejects the TLS certificate that Node.js presents. This is different from a client-side rejection (where the client rejects the server's certificate); here, the server is telling Node.js "I don't accept your certificate." The "tlsv1 alert bad certificate" message is a TLS protocol-level alert indicating that the peer found the presented certificate unacceptable. This typically happens when: - The certificate is self-signed or not signed by a trusted CA - The certificate chain is incomplete or missing intermediate certificates - The certificate has expired or is not yet valid - The certificate CN/SAN doesn't match the expected domain - The server has stricter certificate validation enabled
Check if your client certificate is still valid:
openssl x509 -in your-certificate.pem -text -noout | grep -A 2 "Validity"Look for:
- Not Before date (should be in the past)
- Not After date (should be in the future)
If the certificate has expired, you need to obtain a new one from your Certificate Authority.
Verify the certificate Subject and Subject Alternative Names match what the server expects:
openssl x509 -in your-certificate.pem -text -noout | grep -A 5 "Subject:"
openssl x509 -in your-certificate.pem -text -noout | grep -A 5 "Alternative Name"Ensure the CN (Common Name) or SAN contains the correct domain or identifier that the server is expecting.
Check if you have the complete certificate chain including intermediate certificates:
openssl verify -untrusted chain.pem your-certificate.pemIf the chain is incomplete, request the intermediate certificates from your Certificate Authority and combine them:
cat your-certificate.pem intermediate1.pem intermediate2.pem > full-chain.pemThen use the full chain in your Node.js code:
const https = require('https');
const fs = require('fs');
const tls = require('tls');
const options = {
key: fs.readFileSync('your-key.pem'),
cert: fs.readFileSync('full-chain.pem'), // Use complete chain
ca: fs.readFileSync('server-ca.pem'), // Server's CA if needed
};
const req = https.request('https://server.example.com', options, (res) => {
console.log('Connected');
});Verify your certificate is in the correct format (PEM) and not corrupted:
# Check if it's valid PEM format
openssl x509 -in your-certificate.pem -text -nooutThe file should contain:
- -----BEGIN CERTIFICATE-----
- Base64 encoded data
- -----END CERTIFICATE-----
If you have a DER format certificate, convert it to PEM:
openssl x509 -inform DER -in your-certificate.der -out your-certificate.pemUse OpenSSL to test if the server accepts your certificate:
openssl s_client -connect server.example.com:443 \
-cert your-certificate.pem \
-key your-key.pem \
-CAfile ca.pemThis simulates what Node.js is doing. Look for:
- Verify return code: 0 (ok) - Certificate accepted
- alert bad certificate - Certificate rejected by server
If OpenSSL also fails, the issue is with the certificate itself, not Node.js.
In your Node.js application, ensure you're passing the certificate correctly:
const https = require('https');
const fs = require('fs');
const options = {
hostname: 'server.example.com',
port: 443,
path: '/',
method: 'GET',
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem'),
// Include CA if server uses self-signed or non-standard CA
ca: fs.readFileSync('./ca.pem'),
// Optional: pin certificate for extra security
// checkServerIdentity: (host, cert) => {
// // Custom validation logic
// }
};
const req = https.request(options, (res) => {
console.log('Status:', res.statusCode);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error('Error:', e.message);
});
req.end();Run your Node.js application with TLS debugging enabled to see the exact TLS handshake:
NODE_DEBUG=tls node your-app.jsOr programmatically:
process.env.NODE_DEBUG = 'tls';
// Then require https and make requests
const https = require('https');The output will show the complete TLS handshake and indicate where the certificate validation fails. Look for certificate exchange messages and error alerts.
If you've verified your certificate is valid and properly formatted:
1. Contact the server's administrator and provide your certificate details
2. Ask them to verify their certificate validation rules
3. Request that they add your client certificate (or its CA) to their trust store
4. Confirm they support mTLS if that's what the connection requires
5. Ask if there are specific certificate requirements (key algorithm, signature algorithm, extensions)
Mutual TLS (mTLS): This error is common in mutual TLS scenarios where both client and server authenticate each other. If this is your use case, ensure:
- Your certificate is signed by a CA that the server trusts
- The certificate includes proper key usage and extended key usage extensions
- The certificate CN/SAN matches what the server expects
Certificate Pinning: If the server uses certificate pinning, ensure your certificate matches the pinned value. You can implement pinning in Node.js by comparing the certificate's public key hash.
Self-Signed Certificates: For development with self-signed certificates, you must explicitly provide the CA:
const options = {
ca: fs.readFileSync('./self-signed-ca.pem')
};Environment Variables: For applications where you cannot modify code, use:
- NODE_EXTRA_CA_CERTS=/path/to/ca.pem - Add custom CAs
- This is cleaner than setting process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' (which disables all validation)
Protocol Version Mismatch: Ensure both client and server support the same TLS version. You can explicitly set the protocol:
const options = {
minVersion: tls.TLS1_2_VERSION,
maxVersion: tls.TLS1_3_VERSION
};Error: EMFILE: too many open files, watch
EMFILE: fs.watch() limit exceeded
Error: Middleware next() called multiple times (next() invoked twice)
Express middleware next() called multiple times
Error: Worker failed to initialize (worker startup error)
Worker failed to initialize in Node.js
Error: EMFILE: too many open files, open 'file.txt'
EMFILE: too many open files
Error: cluster.fork() failed (cannot create child process)
cluster.fork() failed - Cannot create child process