Skip to content
ecdsa.com
Node.js tls.connect / fetch (undici)Node.js crypto

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

How to fix it

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

Browse the full signature error database