This error occurs when Node.js cannot locate the TLS certificate files required to establish a secure connection. It typically indicates missing, misconfigured, or inaccessible certificate paths in your HTTPS/TLS server setup.
The 'No certificates were found' error means Node.js tried to create a secure TLS context but could not find the certificate file(s) you specified. This happens when using tls.createSecureContext(), https.createServer(), or similar methods with TLS options. Node.js needs both a certificate (cert) and private key (key) file to establish encrypted connections. If these files are missing, have incorrect paths, or cannot be read due to permissions issues, this error is thrown.
First, confirm the certificate and key files are physically present on disk:
# Check if files exist
ls -la /path/to/your/cert.pem
ls -la /path/to/your/key.pem
# On Windows, use dir instead
dir C:\\path\\to\\cert.pemIf files don't exist, you need to either generate them (for self-signed) or obtain them from your Certificate Authority.
One of the most common issues is using relative paths that may not resolve correctly. Always use absolute paths or construct them dynamically:
const fs = require('fs');
const https = require('https');
const path = require('path');
// BAD: Relative path
const options = {
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem'),
};
// GOOD: Absolute path using path.join with __dirname
const options = {
cert: fs.readFileSync(path.join(__dirname, '../certs/cert.pem')),
key: fs.readFileSync(path.join(__dirname, '../certs/key.pem')),
};
// GOOD: Full absolute path
const options = {
cert: fs.readFileSync('/etc/ssl/certs/cert.pem'),
key: fs.readFileSync('/etc/ssl/private/key.pem'),
};Verify that the Node.js process can read the certificate files:
# Check current file permissions
ls -l /path/to/cert.pem
ls -l /path/to/key.pem
# Ensure the file is readable (owner must have read permission)
chmod 644 /path/to/cert.pem
chmod 600 /path/to/key.pem # Key should be more restricted
# If running as a different user, ensure they own the files or belong to right group
chown nodeuser:nodeuser /path/to/cert.pem
chown nodeuser:nodeuser /path/to/key.pemOn Linux, the Node.js process must have read permissions for the certificate files.
Add try-catch to get a clearer error message about which file is missing:
const fs = require('fs');
const https = require('https');
const path = require('path');
try {
const cert = fs.readFileSync(path.join(__dirname, 'cert.pem'));
const key = fs.readFileSync(path.join(__dirname, 'key.pem'));
const options = { cert, key };
const server = https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello HTTPS!');
});
server.listen(443, () => console.log('HTTPS server running'));
} catch (err) {
console.error('Failed to load certificates:', err.message);
process.exit(1);
}This helps identify which specific file is missing.
Ensure your certificate files are in PEM format (text, not binary):
# Check if certificate is in PEM format (should start with -----BEGIN)
head -1 /path/to/cert.pem
# Should output: -----BEGIN CERTIFICATE-----
# Check if key is in PEM format
head -1 /path/to/key.pem
# Should output: -----BEGIN RSA PRIVATE KEY----- or -----BEGIN PRIVATE KEY-----If the file is binary or in DER format, convert it using OpenSSL:
# Convert DER certificate to PEM
openssl x509 -inform DER -in cert.der -out cert.pem
# Convert DER key to PEM
openssl rsa -inform DER -in key.der -out key.pemFor production deployments, use environment variables for certificate paths:
const fs = require('fs');
const https = require('https');
const path = require('path');
const certPath = process.env.CERT_PATH || path.join(__dirname, 'cert.pem');
const keyPath = process.env.KEY_PATH || path.join(__dirname, 'key.pem');
try {
const options = {
cert: fs.readFileSync(certPath),
key: fs.readFileSync(keyPath),
};
const server = https.createServer(options, handler);
server.listen(process.env.PORT || 443);
} catch (err) {
console.error(`Certificate loading failed: ${err.message}`);
console.error(`Looked for cert at: ${certPath}`);
console.error(`Looked for key at: ${keyPath}`);
process.exit(1);
}Then set environment variables in your deployment:
export CERT_PATH=/etc/ssl/private/cert.pem
export KEY_PATH=/etc/ssl/private/key.pemCertificate Chain: If using a certificate signed by a Certificate Authority, you may need to include intermediate certificates. Use the ca option with an array of CA certificates:
const options = {
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem'),
ca: [fs.readFileSync('intermediate1.pem'), fs.readFileSync('intermediate2.pem')],
};Self-Signed Certificates: For development, generate self-signed certificates using OpenSSL:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodesContainer Deployments: When using Docker, ensure certificate files are mounted as volumes or copied during the build. Common mistake is using a host path that doesn't exist in the container:
# In Dockerfile
COPY certs/ /app/certs/
# In docker-compose.yml
volumes:
- ./certs:/app/certs:roModule Bundling: If using tools like webpack or bundlers, certificate paths become invalid after bundling. Always use environment-based paths or load certificates at runtime from the filesystem, never try to bundle certificate files.
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