How to fix Error: tlsv1 alert bad certificate (peer rejected certificate) in Node.js

Node.jsINTERMEDIATEHIGHUpdated Dec 9, 2025ยท 129 views

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.

Quick fix

Fixes Error: tlsv1 alert bad certificate (peer rejected certificate)

openssl x509 -in your-certificate.pem -text -noout | grep -A 2 "Validity"
  1. Verify the certificate validity and dates
  2. Check the certificate subject and SAN
  3. Verify the complete certificate chain
  4. Ensure proper certificate format and encoding
node.js โ€” error
openssl x509 -in your-certificate.pem -text -noout | grep -A 2 "Validity"
Error: tlsv1 alert bad certificate (peer rejected certificate)

What this error means

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

Typical symptoms

  • HTTPS requests to a specific server fail with TLS alert error
  • The application works fine with different servers but fails with one particular endpoint
  • Error occurs during the TLS handshake, before any data is sent
  • Adding --insecure flag or disabling certificate validation temporarily fixes the issue
  • Other clients (curl, browsers) may accept the same certificate without issues

Common causes

  1. Server is configured to reject certificates it doesn't recognize (mutual TLS/mTLS without proper client certificate)
  2. Client certificate is self-signed and not in the server's trusted CA store
  3. Client certificate chain is incomplete (missing intermediate certificates)
  4. Client certificate CN/SAN (Subject Alternative Name) doesn't match the connection details
  5. Client certificate has expired or not yet become valid
  6. Server requires certificate pinning and your certificate doesn't match the pinned hash
  7. Misconfigured mutual TLS (mTLS) authentication requiring specific client certificates

How to fix "Error: tlsv1 alert bad certificate (peer rejected certificate)"

1Verify the certificate validity and dates

Check if your client certificate is still valid:

bash
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.

2Check the certificate subject and SAN

Verify the certificate Subject and Subject Alternative Names match what the server expects:

bash
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.

3Verify the complete certificate chain

Check if you have the complete certificate chain including intermediate certificates:

bash
openssl verify -untrusted chain.pem your-certificate.pem

If the chain is incomplete, request the intermediate certificates from your Certificate Authority and combine them:

bash
cat your-certificate.pem intermediate1.pem intermediate2.pem > full-chain.pem

Then use the full chain in your Node.js code:

javascript
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');
});
4Ensure proper certificate format and encoding

Verify your certificate is in the correct format (PEM) and not corrupted:

bash
# Check if it's valid PEM format
openssl x509 -in your-certificate.pem -text -noout

The file should contain:
- -----BEGIN CERTIFICATE-----
- Base64 encoded data
- -----END CERTIFICATE-----

If you have a DER format certificate, convert it to PEM:

bash
openssl x509 -inform DER -in your-certificate.der -out your-certificate.pem
5Test the certificate with OpenSSL

Use OpenSSL to test if the server accepts your certificate:

bash
openssl s_client -connect server.example.com:443 \
  -cert your-certificate.pem \
  -key your-key.pem \
  -CAfile ca.pem

This 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.

6Configure Node.js with the correct certificate

In your Node.js application, ensure you're passing the certificate correctly:

javascript
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();
7Enable TLS debugging for detailed diagnostics

Run your Node.js application with TLS debugging enabled to see the exact TLS handshake:

bash
NODE_DEBUG=tls node your-app.js

Or programmatically:

javascript
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.

8Contact the server administrator

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)

Advanced notes

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:

javascript
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:

javascript
const options = {
  minVersion: tls.TLS1_2_VERSION,
  maxVersion: tls.TLS1_3_VERSION
};

Frequently asked questions

What does "Error: tlsv1 alert bad certificate (peer rejected certificate)" mean?
js presents. " The "tlsv1 alert bad certificate" message is a TLS protocol-level alert indicating that the peer found the presented certificate unacceptable.
How do I fix "Error: tlsv1 alert bad certificate (peer rejected certificate)"?
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.
What causes "Error: tlsv1 alert bad certificate (peer rejected certificate)"?
Server is configured to reject certificates it doesn't recognize (mutual TLS/mTLS without proper client certificate) Client certificate is self-signed and not in the server's trusted CA store Client certificate chain is incomplete (missing intermediate certificates)
Is the "Error: tlsv1 alert bad certificate (peer rejected certificate)" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading