kubectl "net/http: TLS handshake timeout" - Fix API Server TLS in CI
By Kaveh Alemi·Latchkey
kubectl opened the TCP connection but the TLS handshake did not complete in time. The endpoint is reachable but slow or overloaded, or a proxy/load balancer is interfering with the handshake. It is often transient.
What this error means
kubectl fails with Unable to connect to the server: net/http: TLS handshake timeout. Unlike a flat i/o timeout, the TCP connection succeeded - the delay is in the TLS negotiation. A retry frequently works.
kubectl output
Unable to connect to the server: net/http: TLS handshake timeout
Common causes
Overloaded or cold API endpoint
A control plane under load, or a load balancer with cold/unhealthy targets, completes the TCP connect but stalls the TLS handshake until it times out.
Proxy or MITM interfering
A corporate proxy, HTTPS_PROXY misconfiguration, or a TLS-inspecting middlebox between the runner and the API server disrupts the handshake.
How to fix it
Retry with backoff
Because the handshake stall is usually transient, a bounded retry clears most occurrences.
Terminal
for i in 1 2 3; do
kubectl version --request-timeout=30s && break
sleep $((i*5))
done
Rule out a proxy and check endpoint health
Check HTTPS_PROXY/NO_PROXY - the API host may need to bypass a TLS-inspecting proxy.
Confirm the API load balancer targets are healthy (control plane not overloaded).
Test the handshake directly: openssl s_client -connect <api-host>:443.
How to prevent it
Add NO_PROXY entries so the API host bypasses TLS-inspecting proxies.
Wrap initial cluster calls in a bounded retry.
Keep the control plane appropriately sized so handshakes are not starved under load.
Frequently asked questions
What causes ""TLS handshake timeout""?
A control plane under load, or a load balancer with cold/unhealthy targets, completes the TCP connect but stalls the TLS handshake until it times out.
How do I fix "TLS handshake timeout"?
Because the handshake stall is usually transient, a bounded retry clears most occurrences.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.