Error message
code: 'ERR_SSL_WRONG_VERSION_NUMBER'
Also printed as
- ERR_SSL_WRONG_VERSION_NUMBER
The full message embeds a thread id and a source path, e.g. "60747095FFFF0000:error:0A00010B:SSL routines:tls_validate_record_header:wrong version number:../deps/openssl/openssl/ssl/record/methods/tlsany_meth.c:77:", so search by the code. tls.connect() and fetch() set code ERR_SSL_WRONG_VERSION_NUMBER; https.request() reports the same reason as "write EPROTO …" with code EPROTO.
Node.js tls.connect / fetch (undici) — OpenSSL SSL_R_WRONG_VERSION_NUMBER; https.request reports it as write EPROTO
What it means
Node.js began a TLS handshake and the reply was not a TLS record, so OpenSSL failed while validating the record header. The peer is speaking plain text on that port: an HTTP server, a proxy expecting plain HTTP, or an SMTP server before STARTTLS. Nothing is wrong with certificates or TLS versions despite the name.
Why it happens
https:// to a port that serves plain HTTP
commonLocal dev servers, internal services behind a TLS-terminating proxy, or a wrong port number in an environment variable.
HTTPS_PROXY or npm's https-proxy written as https://
commonMost forward proxies take plain HTTP from the client and open a CONNECT tunnel; an https:// proxy URL makes the client start TLS with the proxy itself.
Implicit TLS against a STARTTLS port
occasionalMail libraries configured with secure: true on port 587 or 25 try TLS immediately, while the server expects the plain SMTP greeting first.
How to fix it
- 1.
Find out what the port speaks
Ask the port over http://; if it answers, use http:// or the real TLS port.
bash curl -si http://127.0.0.1:8080/ | head -1 # HTTP answers: use http:// or the TLS port openssl s_client -connect 127.0.0.1:8443 -brief </dev/null - 2.
Write proxy URLs with http://
The scheme of the proxy URL describes the connection to the proxy, not to the destination; HTTPS destinations still get end-to-end TLS through the tunnel.
bash # Proxy URLs for HTTPS traffic normally start with http:// (CONNECT tunnel) export HTTPS_PROXY=http://proxy.example.net:3128 npm config set https-proxy http://proxy.example.net:3128 - 3.
Mail: use STARTTLS on 587, implicit TLS on 465
With nodemailer, secure: true belongs to port 465; on 587 keep secure: false and require STARTTLS.
js // SMTP: secure: true only for implicit TLS (465); 587 upgrades with STARTTLS import nodemailer from "nodemailer"; const transport = nodemailer.createTransport({ host: "smtp.example.com", port: 587, secure: false, requireTLS: true });
Related errors
curl: (35) TLS connect error: error:0A00010B:SSL routines::wrong version numbercurl (OpenSSL backend)SSL routines:tls_validate_record_header:wrong version numberOpenSSL 3 (openssl s_client and any OpenSSL-based client)[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)http: server gave HTTP response to HTTPS clientGo net/http