How to fix Error: error:0906D06C:PEM routines:PEM_read_bio:no start line in Node.js
This error occurs when Node.js attempts to read a certificate or private key file that is not properly formatted in PEM format. The OpenSSL library cannot find the required PEM header markers or the file structure is malformed.
Quick fix
Fixes 0906D06C
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJ... (base64 content)
... (more lines)
-----END CERTIFICATE------ Verify PEM file has proper headers and footers
- Check for proper line breaks after headers
- Confirm you are using the correct files
- Test certificate validity with OpenSSL
-----BEGIN CERTIFICATE-----MIIDXTCCAkWgAwIBAgIJAKJ... (base64 content)... (more lines)-----END CERTIFICATE-----Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
What this error means
This error originates from OpenSSL's PEM parsing routines when Node.js tries to load TLS/SSL certificates or private keys. PEM (Privacy Enhanced Mail) is a base64-encoded format that requires specific header and footer markers. The "no start line" message means the OpenSSL library could not find a valid PEM header like `-----BEGIN CERTIFICATE-----` or `-----BEGIN PRIVATE KEY-----`, or the file structure doesn't match the expected PEM format. This commonly happens when setting up HTTPS servers, configuring TLS clients, or working with JWT signing keys. The Node.js `https`, `tls`, and `crypto` modules all rely on OpenSSL to parse these files, so any formatting issue will trigger this error.
Typical symptoms
- HTTPS server fails to start with PEM parsing error
- TLS connection establishment fails immediately
- Error occurs when calling fs.readFileSync() on certificate files
- JWT signing or verification throws OpenSSL error
- Works in some environments but fails in others (Docker, production)
- Certificate that worked previously now fails after copy/paste
Common causes
- Certificate or key file missing required PEM header (-----BEGIN CERTIFICATE-----) or footer (-----END CERTIFICATE-----)
- PEM content formatted on a single line without newline characters after headers
- Escaped newline characters (\n) stored as literal string instead of actual line breaks
- Wrong file specified - using certificate where private key is expected or vice versa
- Certificate retrieved from database or environment variable without proper newline preservation
- File encoding issues - using UTF-16 or other encodings instead of UTF-8/ASCII
- Incomplete certificate content - file truncated or partially copied
- Extra whitespace, BOM markers, or invisible characters before PEM header
How to fix "Error: error:0906D06C:PEM routines:PEM_read_bio:no start line"
Open your certificate or key file and confirm it has the required markers:
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJ... (base64 content)
... (more lines)
-----END CERTIFICATE-----For private keys:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhki... (base64 content)
-----END PRIVATE KEY-----Or for RSA keys:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA... (base64 content)
-----END RSA PRIVATE KEY-----If these markers are missing, your file is not in PEM format.
PEM files must have actual newline characters. If your certificate looks like this:
-----BEGIN CERTIFICATE-----MIIDXTCCAkWgAwIBA...-----END CERTIFICATE-----It needs newlines added:
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBA...
(64-character lines)
-----END CERTIFICATE-----If loading from environment variables or databases, ensure newlines are preserved:
const privateKey = process.env.PRIVATE_KEY.replace(/\\n/g, '\n');Verify your HTTPS/TLS configuration uses the right files:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('path/to/private-key.pem'), // Private key here
cert: fs.readFileSync('path/to/certificate.pem') // Certificate here
};
const server = https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello secure world!');
});Common mistakes:
- Swapping the key and cert files
- Using a certificate when a CA bundle is expected
- Missing intermediate certificates in chain
Use OpenSSL command-line tools to verify the file format:
For certificates:
openssl x509 -in certificate.pem -text -nooutFor private keys:
openssl rsa -in private-key.pem -checkIf these commands fail with similar errors, the file is definitely malformed. If they succeed but Node.js still fails, check for file encoding issues:
file certificate.pem
# Should show: ASCII text or UTF-8 Unicode textWhen loading certificates from environment variables (common in Docker/cloud deployments):
// Wrong - treats \n as literal characters
const cert = process.env.SSL_CERT;
// Correct - converts escaped newlines to actual newlines
const cert = process.env.SSL_CERT.replace(/\\n/g, '\n');
// Alternative: use Buffer
const cert = Buffer.from(process.env.SSL_CERT, 'base64').toString('utf8');In your .env file or environment configuration:
# Multi-line format (preferred)
SSL_CERT="-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJ...
-----END CERTIFICATE-----"
# Or single-line with \n (must be unescaped in code)
SSL_CERT="-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWg...\n-----END CERTIFICATE-----"Ensure the file is saved as UTF-8 without BOM:
# Check encoding
file -i certificate.pem
# Convert if necessary
iconv -f UTF-16 -t UTF-8 certificate.pem > certificate-utf8.pemRemove any BOM markers or trailing whitespace:
# Remove BOM
sed -i '1s/^\xEF\xBB\xBF//' certificate.pem
# Remove trailing whitespace
sed -i 's/[[:space:]]*$//' certificate.pemYou can also regenerate a clean PEM file from the certificate:
openssl x509 -in certificate.crt -out certificate.pem -outform PEMAdvanced notes
Certificate Chain Ordering: When providing a certificate chain, the order matters. Your server certificate should come first, followed by intermediate certificates, then the root CA. Each certificate needs its own PEM headers/footers:
-----BEGIN CERTIFICATE-----
(your server cert)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(intermediate cert)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(root CA cert)
-----END CERTIFICATE-----Alternative PEM Headers: Different key types use different headers. Modern keys use -----BEGIN PRIVATE KEY----- (PKCS#8), while older RSA keys use -----BEGIN RSA PRIVATE KEY-----. Node.js supports both formats.
Docker and CI/CD Considerations: When mounting secrets in containers, ensure volume mounts preserve newlines. Some orchestration platforms base64-encode secrets by default, requiring decoding before use.
passphrase-protected Keys: If your private key requires a passphrase, provide it in the options:
const options = {
key: fs.readFileSync('encrypted-key.pem'),
passphrase: 'your-passphrase'
};Debugging Production Issues: In production environments where you cannot easily inspect files, log the first and last 50 characters of the loaded certificate (excluding sensitive content) to verify headers are preserved:
const cert = fs.readFileSync('cert.pem', 'utf8');
console.log('First 50:', cert.substring(0, 50));
console.log('Last 50:', cert.substring(cert.length - 50));Frequently asked questions
- What does "0906D06C" mean?
- js tries to load TLS/SSL certificates or private keys. PEM (Privacy Enhanced Mail) is a base64-encoded format that requires specific header and footer markers. The "no start line" message means the OpenSSL library could not find a valid PEM header like -----BEGIN CERTIFICATE----- or -----BEGIN PRIVATE KEY-----, or the file structure doesn't match the expected PEM format.
- How do I fix "0906D06C"?
- This error occurs when Node.js attempts to read a certificate or private key file that is not properly formatted in PEM format. The OpenSSL library cannot find the required PEM header markers or the file structure is malformed.
- What causes "0906D06C"?
- Certificate or key file missing required PEM header (-----BEGIN CERTIFICATE-----) or footer (-----END CERTIFICATE-----) PEM content formatted on a single line without newline characters after headers Escaped newline characters (\n) stored as literal string instead of actual line breaks
- Is the "0906D06C" 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
- ๐Node.js Official Documentation
- ๐Node.js Crypto Module Documentation(Official Docs)
- ๐
- ๐