Quick answer
SSL certificate error in code most often occurs due to certificate expiration, untrusted certificate chain, or wrong hostname. It is fixed by checking dates, updating the CA store, and properly configuring the client, not by disabling verification.
How to recognize the problem
- Application throws `CERT_HAS_EXPIRED` or `certificate has expired` error
- `UNABLE_TO_VERIFY_LEAF_SIGNATURE` or `self signed certificate in certificate chain` appears
- `ERR_TLS_CERT_ALTNAME_INVALID` due to wrong hostname
- Connection works in browser but not in code
- Error occurs only in one environment (e.g., staging)
Most common causes
Expired certificate
The certificate on the server has expired or the client has cached an older chain. Check the validity date and refresh the cache.
Untrusted issuer (CA)
The client does not recognize the CA that issued the certificate, which is common with internal or self-signed certificates. The CA needs to be added to the trust store.
Wrong hostname
The certificate was issued for a different name (e.g., `example.com` instead of `api.example.com`). Check the SAN field and how the client accesses it.
Invalid certificate chain
The server does not send complete intermediate certificates, so the client cannot build the chain to the root. This is fixed by proper server configuration.
Wrong system time
If the clock on the computer or container is wrong, a valid certificate appears expired or not yet valid.
Step-by-step fix
- 1
Read the exact error message
Look for the error code in the log (e.g.,
CERT_HAS_EXPIRED,UNABLE_TO_VERIFY_LEAF_SIGNATURE,ERR_TLS_CERT_ALTNAME_INVALID). Different codes indicate different causes, so do not skip this step. - 2
Check the certificate validity date
Open the site in a browser and click the padlock next to the address, then view the certificate details for the start and end dates. Or in the terminal run
openssl s_client -connect host:443 -servername host -textand look at theNot BeforeandNot Afterfields. - 3
Check if the hostname matches
In the same
openssloutput, find theSubject Alternative Namefield. It must contain the name you use in the code. If you access via IP address, the certificate will likely be invalid. - 4
Update the CA store on the system
On Windows (as administrator) run
certutil -generateSSTFromWU roots.sstthencertutil -addstore root roots.sst; add a single certificate withcertutil -addstore root certificate.crt. Only add CAs you trust. On Linux (Debian/Ubuntu)sudo update-ca-certificates, and on macOS double-click the.crt, add it to theSystemkeychain and setAlways Trustfor that CA. - 5
Add the internal CA in code
If you use an internal or self-signed certificate, pass the path to the CA file in the code. In Node.js this is the
caoption inhttps.requestor theNODE_EXTRA_CA_CERTS=/path/to/ca.crtvariable. In Pythonrequestsuseverify='/path/to/ca.crt'. - 6
Fix the chain on the server
Make sure the server sends full certificate chains. In Nginx configuration
ssl_certificateshould contain the server certificate and the list of intermediate certificates, with the server certificate first. Verify withopenssl s_client -showcerts -servername host -connect host:443. - 7
Check the system time
On Windows (as administrator)
w32tm /resync, on Linuxtimedatectlandsudo systemctl restart systemd-timesyncd. In Docker containers check if the time is synchronized with the host. - 8
Temporarily bypass verification only in development
If you must continue development, temporarily disable verification, but never in production. In Node.js
NODE_TLS_REJECT_UNAUTHORIZED=0(local only), in Pythonverify=Falsewithurllib3.disable_warnings(). Be sure to remove before committing.
If nothing helps: isolate the problem
If the error persists, create a minimal reproducible example: a script that only establishes a TLS connection to the same host. Test it from different networks and computers. Compare the openssl s_client output with what the client sees. Check if a proxy or antivirus intercepts traffic and changes the certificate. In Docker, check if the container has CA certificates installed (ca-certificates package). If the problem is only in production, compare environment configuration and client versions. For complex chains and mTLS, use tools like openssl verify and curl -v to see the exact flow.
How to prevent it
- Regularly check certificate expiration dates and set reminders
- Use automated renewal (e.g., Let's Encrypt) and test renewal
- In development use `mkcert` for local certificates instead of permanently disabling verification
- Never commit code containing `rejectUnauthorized: false` or `verify=False`
When to call a professional
If the error involves mTLS, complex certificate chains, or occurs only on production servers, contact IT support to isolate the problem without risk of downtime.
Software and product development · Custom apps, SaaS and an MVP in 4 to 8 weeksFAQ
Why do I get `self signed certificate in certificate chain`?
This means the client does not trust the certificate in the chain, most often because it is self-signed or from an internal CA. The solution is to add that CA to the trust store or pass the path to the CA file in the code.
Is it safe to disable certificate verification in code?
No, disabling verification (`rejectUnauthorized: false` or `verify=False`) makes the application vulnerable to interception attacks. Use it only temporarily in local development and never in production.
How can I check which certificate the server actually sends?
Run `openssl s_client -connect host:443 -servername host -showcerts -text`. In the output you will see all certificates in the chain, and the text part shows details of the server certificate, including validity dates and SAN fields.