[BUG] SSL certificate has expired not working since 2.1.190+ on mac

Status Fixed / completed
Reported on v2.1.170
Maintainer reply None cached
Activity 12 comments · opened Jun 26, 2026 · closed Aug 17, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

I'm getting this error in the cli:
Unable to connect to API: SSL certificate has expired
I already set NODE_EXTRA_CA_CERTS with the correct pem and validated it.
If I install 2.1.170 it works well but then in 2.1.190+ it fails with that message, regardless of the NODE_EXTRA_CA_CERTS

Claude desktop works well
Tried with

cat ~/.claude/settings.json
{
    "theme": "dark",
    "env": {
    "NODE_EXTRA_CA_CERTS": "cert.pem"
}

Using a CASB

Using /doctor or /bug didn't not work neither

What Should Happen?

It should allow me to use the cli

Error Messages/Logs

✻ Unable to connect to API: SSL certificate has expired · Retrying in 2s · attempt 3/10

Steps to Reproduce

Open Claude cli and talk

Claude Model

_No response_

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.170

Claude Code Version

2.1.190

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

11 Comments

yurukusa · 2 months ago

(Another user.) A few concrete things to try, in order — the first one is the most likely culprit given your settings.

1. NODE_EXTRA_CA_CERTS must be an absolute path. Your settings has "NODE_EXTRA_CA_CERTS": "cert.pem" — a relative path. Node resolves NODE_EXTRA_CA_CERTS relative to the process working directory, not ~/.claude, so unless you happen to launch from the dir that contains cert.pem, Node silently loads nothing and you're back to the default CA store (which won't trust your CASB's intercept cert). Use the full path:

{ "env": { "NODE_EXTRA_CA_CERTS": "/Users/<you>/.claude/cert.pem" } }

2. Also export it in the shell, not only in settings.json. The env block in settings.json is applied by Claude Code after startup; the very first TLS connection can happen before that. Setting it in the actual environment removes that timing question:

export NODE_EXTRA_CA_CERTS="/Users/<you>/.claude/cert.pem"
claude "test"

If it works from the shell but not from settings.json, that's the timing/ordering bug to report.

3. Confirm the cert in the chain isn't actually expired. The message "SSL certificate has expired" (vs. "self-signed" / "unable to get local issuer") means a cert in the presented chain is past its notAfter — adding a CA won't fix an expired one. Check what your CASB is presenting and your pem's dates:

openssl x509 -enddate -noout -in /Users/<you>/.claude/cert.pem
echo | openssl s_client -connect api.anthropic.com:443 -showcerts 2>/dev/null | openssl x509 -noout -enddate

If the CASB's intercept/root cert has expired, the CASB admin has to renew it — that part is outside Claude Code.

The regression angle for Anthropic: works on 2.1.170, fails on 2.1.190+ with the same NODE_EXTRA_CA_CERTS. That strongly suggests 2.1.190 changed cert handling — e.g. a bundled-Node bump with stricter chain validation, or the env var no longer being honored. Worth noting in the report that the var is set and validated, the only variable is the CLI version, and that Claude Desktop (different runtime) is unaffected — that narrows it to the CLI's TLS stack between those two builds.

medalliaerlich · 2 months ago

Hey yes I've put the relative path in the description to don't naming and
location details but I'm using absolute path

El vie, 26 de jun de 2026, 5:34 p.m., ゆる草 @.***>
escribió:

yurukusa left a comment (anthropics/claude-code#71663) <https://github.com/anthropics/claude-code/issues/71663#issuecomment-4813229081> (Another user.) A few concrete things to try, in order — the first one is the most likely culprit given your settings. 1. NODE_EXTRA_CA_CERTS must be an absolute path. Your settings has "NODE_EXTRA_CA_CERTS": "cert.pem" — a relative path. Node resolves NODE_EXTRA_CA_CERTS relative to the process working directory, not ~/.claude, so unless you happen to launch from the dir that contains cert.pem, Node silently loads nothing and you're back to the default CA store (which won't trust your CASB's intercept cert). Use the full path: { "env": { "NODE_EXTRA_CA_CERTS": "/Users/<you>/.claude/cert.pem" } } 2. Also export it in the shell, not only in settings.json. The env block in settings.json is applied by Claude Code after startup; the very first TLS connection can happen before that. Setting it in the actual environment removes that timing question: export NODE_EXTRA_CA_CERTS="/Users/<you>/.claude/cert.pem" claude "test" If it works from the shell but not from settings.json, that's the timing/ordering bug to report. 3. Confirm the cert in the chain isn't actually expired. The message "SSL certificate has expired" (vs. "self-signed" / "unable to get local issuer") means a cert in the presented chain is past its notAfter — adding a CA won't fix an expired one. Check what your CASB is presenting and your pem's dates: openssl x509 -enddate -noout -in /Users/<you>/.claude/cert.pemecho | openssl s_client -connect api.anthropic.com:443 -showcerts 2>/dev/null | openssl x509 -noout -enddate If the CASB's intercept/root cert has expired, the CASB admin has to renew it — that part is outside Claude Code. The regression angle for Anthropic: works on 2.1.170, fails on 2.1.190+ with the same NODE_EXTRA_CA_CERTS. That strongly suggests 2.1.190 changed cert handling — e.g. a bundled-Node bump with stricter chain validation, or the env var no longer being honored. Worth noting in the report that the var is set and validated, the only variable is the CLI version, and that Claude Desktop (different runtime) is unaffected — that narrows it to the CLI's TLS stack between those two builds. — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/71663?email_source=notifications&email_token=AGVMRZV3EL6UTSK7G4DFMYT5B3M4PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBRGMZDEOJQHAY2M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-4813229081>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AGVMRZTRIKSXSOCCTPZIFVL5B3M4PAVCNFSNUABFKJSXA33TNF2G64TZHM4TGNZSGUZTINZVHNEXG43VMU5TINZVGQ3TAOJXGU2KC5QC> . Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS <https://github.com/notifications/mobile/ios/AGVMRZTRGF2B7VB7F6BGMCT5B3M4PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBRGMZDEOJQHAY2M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG> and Android <https://github.com/notifications/mobile/android/AGVMRZX4G7VVPSAQVG3P46L5B3M4PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBRGMZDEOJQHAY2M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA>. Download it today! You are receiving this because you authored the thread.Message ID: @.***>

--

Confidentiality notice: This email and any attachments are confidential
and for the intended recipient only. Unauthorized review, use, disclosure,
copying or distribution is prohibited. If received in error, notify the
sender immediately and delete all copies.

medalliaerlich · 2 months ago

It is also failing on IJ Idea and VS Code, probably because they use CLI internally

JLau-cy · 2 months ago

@medalliaerlich Check your keychain for any expired root certificates. Clearing them out fixed the issue for me.

medalliaerlich · 2 months ago
@medalliaerlich Check your keychain for any expired root certificates. Clearing them out fixed the issue for me.

I did this:

 openssl crl2pkcs7 -nocrl -certfile /certs/<name>.pem | \
  openssl pkcs7 -print_certs -noout -text | grep -A 2 "Validity"

Validity
Not Before: Oct 30 14:32:20 2024 GMT
Not After : Oct 25 14:32:20 2044 GMT

only one and seems correct

glennwiz · 2 months ago

winget install, 2.1.197, DST Root X3 removal didn't help, downgrade to 2.1.177 did.

Chudesnov · 2 months ago
any expired root certificates. Clearing them out fixed the issue for me

Thanks, that seems to work for most people experiencing this issue.

That being said: having _any_ expired root certificates in the keychain should not be a blocker for using a specific admin-trusted SSL certificate that's not expired. Anthropic engineers should still look into this issue.

jarnix · 1 month ago

claude install 2.1.177

yurukusa · 1 month ago

@medalliaerlich You're right, and thanks for the correction — since you were already using an absolute path, my earlier guess about NODE_EXTRA_CA_CERTS was wrong. Retracting it so it doesn't send anyone else down that path.
For anyone landing on this thread later: the fix that actually worked for multiple people here is removing the expired root certificate from the system keychain, as @JLau-cy described above. That matches the reported symptoms much better than my path theory did.

jarnix · 1 month ago

Don"t remove base Windows certificates, MS ships them intentionally.

  • Microsoft Root Authority (expired Dec 2020) and Microsoft Root Certificate Authority (expired May 2021) — roots for huge amounts of Microsoft-signed code and drivers
  • Microsoft Authenticode(tm) Root Authority (expired Jan 2000) and Microsoft Time Stamping Service Root (expired Dec 1999) — legacy code signing and timestamping
  • NO LIABILITY ACCEPTED, (c)97 VeriSign (expired 2004) and Thawte Timestamping CA (expired 2021) — timestamping roots used by countless third-party signed binaries
  • Baltimore CyberTrust Root (expired May 2025) — until recently the root behind Azure/Microsoft services; still around for older chains
medalliaerlich · 1 month ago

Please, just review the changes between 177 and 190 related to ssl certs, some change between those versions broke it

Showing cached comments. Read the full discussion on GitHub ↗