Problem – SSL/TLS Handshake Failure When Calling Anthropic Claude API
Our cloud‑managed service attempts to invoke the Anthropic Claude API over HTTPS. After a scheduled TLS certificate rotation on the Anthropic side, all outbound requests started failing with a handshake error. The failure manifested as immediate connection aborts, no data returned, and a surge in error metrics.
Observed Symptoms
- Python
requestscalls raiseSSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed. - cURL returns
curl: (60) SSL certificate problem: unable to get local issuer certificate. - Application logs show repeated entries similar to:
2026-10-15 03:12:41,872 ERROR [api-client] SSL handshake failed for https://api.anthropic.com/v1/complete:
SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed:
unable to get local issuer certificate (_ssl.c:1129)'))
Impact
- All user‑facing features that rely on Claude completions become unavailable.
- Error rate spikes from <1% to >95% in
api_error_ratemetric. - SLAs breached for downstream services.
Root Cause – Mismatch Between Updated Anthropic CA Chain and Stale Trust Store
Anthropic rotated the leaf certificate for api.anthropic.com and introduced a new intermediate CA signed by a recently added root that is not present in the default certifi bundle used by our runtime environment. The TLS handshake proceeds until the server presents its certificate chain. The client then attempts to build a trust path using the locally trusted roots. Because the new root is missing, the verification step fails, causing the handshake to abort.
Compounding the issue, the service runs on a hardened container image that disables the system ca-certificates package in favor of a pinned certifi version (2023.5.7). The rotation occurred after the image build, so the container never received the updated root CA.
Debug – Step‑by‑Step Investigation
- Confirm the failure with low‑level TLS diagnostics.
- Check the client trust store.
- Inspect the container image.
- Validate that the issue is isolated to the Anthropic endpoint.
- Review recent change logs.
openssl s_client -connect api.anthropic.com:443 -servername api.anthropic.com -showcerts
Sample output (truncated):
...
Certificate chain
0 s:/CN=api.anthropic.com
i:/C=US/O=NewRootCA/OU=Infrastructure/CN=NewRootCA Intermediate
1 s:/C=US/O=NewRootCA/OU=Infrastructure/CN=NewRootCA Intermediate
i:/C=US/O=NewRootCA/OU=Infrastructure/CN=NewRootCA Root
...
Verify return code: 21 (unable to verify the first certificate)
# Python REPL
>>> import certifi, ssl
>>> ssl.create_default_context(cafile=certifi.where()).get_ca_certs()
# Output shows no entry for "NewRootCA Root"
docker run --rm myservice:latest cat /etc/ssl/certs/ca-certificates.crt | grep -i "NewRootCA"
No matches – the root is absent.
curl -v https://www.google.com
# TLS handshake succeeds
2026-10-10 02:00:00 INFO Cert rotation on Anthropic side – new intermediate and root CAs deployed.
Solution – Update Trust Store to Include New Anthropic Root CA
Two viable approaches were evaluated:
| Approach | Pros | Cons |
|---|---|---|
Update certifi dependency to a version that bundles the new root (2024.8.30). |
Minimal code change; respects existing pinning strategy. | Requires redeploy of all services. |
Mount an updated ca-certificates.crt file into the container and configure the HTTP client to use it. |
Can be rolled out via config change; does not affect other dependencies. | Introduces a second source of truth for CAs. |
Implementation – Updating certifi
We chose the first approach to keep a single source of trust anchors.
# requirements.txt (before)
certifi==2023.5.7
requests==2.31.0
# requirements.txt (after)
certifi==2024.8.30
requests==2.31.0
Rebuild and redeploy the container image:
docker build -t myservice:2026.10.15 .
docker push myservice:2026.10.15
kubectl set image deployment/myservice myservice=myrepo/myservice:2026.10.15 --record
Alternative – Mounting Updated CA Bundle
# Create a custom CA bundle on the host
cat /etc/ssl/certs/ca-certificates.crt new_root_ca.pem > /opt/custom-ca/ca-bundle.crt
# Kubernetes pod spec snippet
volumeMounts:
- name: custom-ca
mountPath: /etc/ssl/certs/custom-ca.crt
subPath: ca-bundle.crt
env:
- name: REQUESTS_CA_BUNDLE
value: /etc/ssl/certs/custom-ca.crt
volumes:
- name: custom-ca
configMap:
name: custom-ca-configmap
Verify – Confirm Handshake Success and Functional Operation
- Run the same
openssl s_clientcommand. The verify return code should be0 (ok). - Execute a test request from the service container:
- Check monitoring dashboards –
api_error_rateshould drop back to baseline (<1%). - Review logs for absence of
SSL handshake failedentries.
python - <<'PY'
import requests, json
resp = requests.post(
"https://api.anthropic.com/v1/complete",
json={"model":"claude-2.0","prompt":"Hello"},
timeout=5
)
print(resp.status_code, resp.json())
PY
Expected output:
200 {'completion': 'Hello! How can I assist you today?'}
Prevent – Operational Guardrails for Future Certificate Rotations
- Automated CA bundle refresh. Add a CI step that runs
pip install -U certifiand fails the build if a newer version is available. - Health check for TLS validation. Deploy a periodic job that performs an
openssl s_clientcheck against critical third‑party endpoints and raises an alert on non‑zero verify codes. - Version pinning policy. Pin
certifito a major version but allow minor updates via a weekly dependency bot (e.g., Dependabot) to capture new root CAs. - Runtime fallback. Configure HTTP clients to respect
REQUESTS_CA_BUNDLEenvironment variable, enabling quick overrides without rebuilding images. - Change‑notification subscription. Subscribe to Anthropic’s security mailing list for advance notice of certificate rotations.
Related Topic Hub: LLM Systems Troubleshooting Hub
FAQ
- Why does the handshake succeed with
curlbut fail in Python?
cURL on the host uses the system
ca-certificatesbundle, which was updated automatically. The Python runtime is locked to an oldercertifibundle that lacks the new root, leading to verification failure. - Can I disable certificate verification as a quick fix?
Disabling verification (
verify=False) bypasses TLS security and is not acceptable in production. It also masks the underlying trust issue and may cause downstream compliance failures. - Do I need to update the OpenSSL version?
No. The OpenSSL library in the container supports TLS 1.2/1.3. The failure is purely due to missing trust anchors, not protocol incompatibility.
- How do I know which CA is missing without contacting Anthropic?
Run
openssl s_client -showcertsand compare the presented chain against the local bundle. The first certificate that cannot be matched is the missing root. - Will this issue reappear if Anthropic rotates intermediate certificates again?
Only if the new intermediate is signed by a root not present in the client bundle. Keeping the CA bundle up‑to‑date mitigates recurrence.