Kafka Error Guide: 'SSLHandshakeException: Received fatal alert: handshake_failure'
Fix Kafka SSLHandshakeException handshake_failure: diagnose TLS version mismatch, cipher suite gaps, one-way vs mTLS, missing client cert, and protocol disablement.
- #kafka
- #troubleshooting
- #errors
- #tls
Exact Error Message
A handshake negotiation failure appears the moment a client connects to an SSL listener and the two sides cannot agree on protocol version, cipher suite, or client authentication:
[2026-06-29 08:33:41,902] ERROR [Producer clientId=metrics-producer] Connection to node
-1 (broker-01.kafka.internal/10.0.4.21:9093) failed authentication due to: SSL handshake
failed (org.apache.kafka.clients.NetworkClient)
org.apache.kafka.common.errors.SslAuthenticationException: SSL handshake failed
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alert.createSSLException(Alert.java:131)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:331)
at sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:855)
Related variants for negotiation problems include “SSL handshake failed”, “No appropriate protocol (protocol is disabled or cipher suites are inappropriate)”, “Unsupported TLS version”, and broker-side alerts demanding a client certificate when ssl.client.auth=required.
What the Error Means
handshake_failure is a fatal TLS alert sent during the negotiation phase, before certificate trust is even fully evaluated. The two endpoints could not converge on a mutually acceptable protocol version (e.g. one only allows TLS 1.3 while the other offers up to TLS 1.2) and/or a common cipher suite. It can also mean the broker requires a client certificate (ssl.client.auth=required, i.e. mTLS) but the client presented none.
This is distinct from trust-chain failures. A handshake_failure is about whether the parties can speak the same TLS dialect, whereas PKIX path building failed or bad_certificate is about whether a presented certificate is trusted. Getting the distinction right saves hours: here you tune protocols, ciphers, and client-auth settings — not truststores.
Common Causes
- TLS version mismatch: broker
ssl.enabled.protocols=TLSv1.3only, client JVM offering TLS 1.2, or a legacy client disabled byssl.protocoldefaults. - Cipher suite mismatch:
ssl.cipher.suitesrestricted to a set the peer does not support (common with FIPS or hardened configs). - mTLS expected, no client cert:
ssl.client.auth=requiredon the broker but the client keystore is absent or empty. - Wrong keystore on the client for a mutual-auth listener, so the client cannot present a usable certificate.
- JDK differences: an older JRE without TLS 1.3, or
jdk.tls.disabledAlgorithmsinjava.securityblocking the only common protocol/cipher. - Listener confusion: connecting
SSL/SASL_SSLsettings to a listener configured for a different protocol set.
How to Reproduce the Error
Force a client to offer only TLS 1.2 against a broker that allows only TLS 1.3:
cat > /tmp/tls12-client.properties <<'EOF'
security.protocol=SSL
ssl.enabled.protocols=TLSv1.2
ssl.truststore.location=/etc/kafka/ssl/truststore.jks
ssl.truststore.password=changeit
EOF
kafka-broker-api-versions.sh --bootstrap-server broker-01.kafka.internal:9093 \
--command-config /tmp/tls12-client.properties
The connection fails with SSLHandshakeException: Received fatal alert: handshake_failure because no protocol version is common to both ends.
Diagnostic Commands
All commands below are read-only.
# What protocols/ciphers does the broker offer? (read-only handshake probe)
openssl s_client -connect broker-01.kafka.internal:9093 -tls1_2 </dev/null 2>&1 | head -20
# Negotiate the highest version and show what was chosen
openssl s_client -connect broker-01.kafka.internal:9093 </dev/null 2>&1 | \
grep -E 'Protocol|Cipher|Verify'
# Inspect the broker's enabled protocols, ciphers, and client-auth mode
grep -E 'ssl.enabled.protocols|ssl.cipher.suites|ssl.client.auth|listeners' \
/etc/kafka/server.properties
# Does the client keystore actually contain a key entry (needed for mTLS)?
keytool -list -v -keystore /etc/kafka/ssl/keystore.jks -storepass changeit | \
grep -E 'Alias name|Entry type'
# JVM-level disabled algorithms that can kill a handshake
grep -E 'jdk.tls.disabledAlgorithms' "$JAVA_HOME/conf/security/java.security"
openssl s_client is the fastest way to see which protocol and cipher the broker will accept, isolating a version/cipher mismatch from a trust problem.
Step-by-Step Resolution
- Confirm it is a negotiation failure, not a trust failure:
handshake_failure(this guide) vsPKIX path building failed/bad_certificate(truststore guides). - Probe the broker with
openssl s_clientto learn the protocol and cipher it accepts. Compare against what the client offers. - Align TLS versions. If the broker is TLS 1.3-only, ensure the client JVM supports and enables TLS 1.3 (JDK 11+), or widen
ssl.enabled.protocolsto include a common version. - Reconcile ciphers. If
ssl.cipher.suitesis restricted, ensure both ends share at least one suite; remove an over-tight restriction if needed. - Handle mTLS. If the broker logs that it expected a client certificate, configure a valid client keystore (
ssl.keystore.location) with a key entry, confirmed viakeytool -list -v. - Check
java.securityforjdk.tls.disabledAlgorithmsentries that block the only common protocol/cipher. - Retry with
kafka-broker-api-versions.sh --command-configto validate the handshake without producing data.
Prevention and Best Practices
- Standardize the TLS version floor across brokers and clients (TLS 1.2+ minimum, prefer 1.3) and roll changes to clients before tightening brokers.
- Keep cipher restrictions documented and tested against the actual client JDKs in use.
- Decide one-way vs mutual TLS explicitly; if
ssl.client.auth=required, ensure every client ships a keystore. - Pin a consistent JDK baseline so
jdk.tls.disabledAlgorithmsdifferences do not cause environment-specific handshake breaks. - Add an
openssl s_clientsynthetic probe per client network to catch protocol/cipher drift early. For fast triage, the free incident assistant can classify a handshake alert from the stack trace.
Related Errors
PKIX path building failed— the CA is not trusted; a trust-chain problem, not negotiation.CertificateExpiredException— a valid chain whose certificate has expired.- No subject alternative names found — hostname verification failure after a successful handshake.
SslAuthenticationException/ SSL channel closed — abrupt close, often a plaintext client hitting an SSL listener.
Frequently Asked Questions
Is handshake_failure a certificate trust problem?
No. It is a negotiation failure over protocol version, cipher suite, or required client auth. Trust problems show as PKIX path building failed or bad_certificate.
How do I quickly see what the broker accepts?
Run openssl s_client -connect host:9093 and read the Protocol and Cipher lines. Try -tls1_2/-tls1_3 to test specific versions.
Why does it fail only from one client environment?
Likely a JDK difference — an older JRE without TLS 1.3, or a stricter jdk.tls.disabledAlgorithms in that environment’s java.security.
The broker wants a client certificate. What changed?
ssl.client.auth=required enables mTLS. The client must present a keystore with a valid key entry; one-way TLS clients will hit handshake_failure.
Can I test without sending messages?
Yes. kafka-broker-api-versions.sh --command-config client.properties performs the full TLS handshake and lists API versions without producing.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.