This error occurs when Node.js cannot find any valid cipher suites for establishing a TLS/SSL connection, typically due to invalid cipher configuration, security level conflicts, or incompatible cipher specifications.
This error indicates that Node.js's TLS/SSL layer cannot establish a secure connection because the cipher suite list is either empty, contains only invalid cipher names, or conflicts with the configured security level and TLS version requirements. When Node.js attempts to create a TLS connection, it must negotiate which encryption algorithms (ciphers) to use with the remote server. This negotiation requires at least one mutually supported cipher suite. If the configured cipher list is invalid or incompatible with the TLS version and OpenSSL security level, Node.js raises this error before attempting the connection. The error commonly occurs when developers manually configure ciphers using invalid names, set security levels that exclude all available ciphers, or create conflicts between TLS 1.3 requirements and legacy cipher specifications.
First, verify which cipher suites are actually available in your Node.js installation:
const tls = require('tls');
// List all available ciphers
console.log('Available ciphers:', tls.getCiphers());
// Check TLS version support
const crypto = require('crypto');
console.log('OpenSSL version:', process.versions.openssl);This shows you the valid cipher names you can use. Common ciphers include:
- TLS_AES_128_GCM_SHA256 (TLS 1.3)
- ECDHE-RSA-AES128-GCM-SHA256 (TLS 1.2)
- ECDHE-RSA-AES256-GCM-SHA384 (TLS 1.2)
If you're manually configuring ciphers, ensure you're using actual cipher suite names, not protocol versions:
// ❌ WRONG - Using protocol names as ciphers
const options = {
ciphers: 'TLSv1.2:TLSv1.3' // These are NOT cipher names
};
// ✅ CORRECT - Using actual cipher suite names
const options = {
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'
};
// ✅ BETTER - Use the secure default
const options = {
// Don't specify ciphers unless you have a specific requirement
};Check your code for any ciphers option in tls.createServer(), tls.connect(), or https methods.
If you're using --tls-cipher-list with SECLEVEL, ensure it's compatible with your TLS version:
# ❌ WRONG - SECLEVEL=0 may conflict with TLS 1.3
node --tls-cipher-list=DEFAULT@SECLEVEL=0 app.js
# ✅ CORRECT - Use default security level (2)
node app.js
# ✅ OR - Configure in code for better controlIn code, you can set security level properly:
const tls = require('tls');
const options = {
// Include security level in cipher string
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384@SECLEVEL=1',
minVersion: 'TLSv1.2',
maxVersion: 'TLSv1.3'
};
const server = tls.createServer(options, (socket) => {
console.log('Connection established');
});OpenSSL security levels range from 0 (least secure) to 5 (most secure), with 2 being the default.
Verify that the NODE_CIPHER_LIST environment variable is not set to an invalid value:
# Check if the variable is set
echo $NODE_CIPHER_LIST
# Unset it if it contains invalid ciphers
unset NODE_CIPHER_LIST
# Or set it to a valid cipher list
export NODE_CIPHER_LIST="ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384"In your application startup script or Docker configuration, remove or correct any NODE_CIPHER_LIST settings.
If using TLS 1.3, make sure you have valid TLS 1.3 cipher suites:
const tls = require('tls');
const options = {
// TLS 1.3 cipher suites (use their full names starting with TLS_)
ciphersuites: 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384',
// TLS 1.2 and earlier ciphers (separate option)
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384',
minVersion: 'TLSv1.2',
maxVersion: 'TLSv1.3'
};
const server = tls.createServer(options, (socket) => {
console.log('Secure connection established');
});
server.listen(8443);Note: TLS 1.3 uses the ciphersuites option (plural), while TLS 1.2 and earlier use ciphers (singular).
Use the OpenSSL command-line tool to verify your cipher configuration before using it in Node.js:
# Test cipher list validity
openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'
# Test with security level
openssl ciphers -v 'DEFAULT@SECLEVEL=2'
# List TLS 1.3 ciphers
openssl ciphers -v -s -tls1_3
# Test connection to a server
openssl s_client -connect example.com:443 -tls1_2 -cipher 'ECDHE-RSA-AES128-GCM-SHA256'If OpenSSL cannot parse the cipher list, Node.js won't be able to use it either.
Understanding OpenSSL Security Levels:
OpenSSL security levels (SECLEVEL) enforce minimum security requirements:
- SECLEVEL=0: Everything permitted (not recommended)
- SECLEVEL=1: 80-bit security minimum (legacy)
- SECLEVEL=2: 112-bit security minimum (default, recommended)
- SECLEVEL=3: 128-bit security minimum
- SECLEVEL=4: 192-bit security minimum
- SECLEVEL=5: 256-bit security minimum
Higher security levels exclude weaker ciphers, which can cause "no ciphers available" if your cipher list only contains excluded ciphers.
TLS 1.3 vs TLS 1.2 Cipher Configuration:
TLS 1.3 introduced a smaller, more secure set of cipher suites and requires different configuration:
- TLS 1.3 ciphers are configured via the ciphersuites option
- TLS 1.2 and earlier use the ciphers option
- TLS 1.3 cipher names always start with "TLS_"
- TLS 1.2 cipher names typically start with the key exchange method (ECDHE, DHE, etc.)
Best Practices:
1. Don't configure ciphers unless necessary: Node.js defaults are carefully selected for security and compatibility
2. Avoid command-line cipher configuration: Use application code for better control and testability
3. Use modern TLS versions: Set minVersion: 'TLSv1.2' at minimum
4. Prefer AEAD ciphers: GCM and ChaCha20-Poly1305 are recommended over CBC mode
5. Test changes thoroughly: Cipher changes can break compatibility with legacy clients
Debugging Commands:
# Check Node.js OpenSSL configuration
node -p "process.versions.openssl"
node -p "require('tls').getCiphers().length"
# Verbose TLS debugging
NODE_DEBUG=tls node app.js
# Test specific cipher
openssl s_client -connect localhost:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384' -debugError: 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