Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kafka By James Joyner IV · · 9 min read

Kafka Error Guide: 'SslAuthenticationException: SSL channel closed' Failed to Send SSL Close Message

Fix Kafka SSL channel closed: diagnose plaintext clients hitting SSL listeners, wrong security.protocol, abrupt connection drops, and proxy/LB TLS termination.

  • #kafka
  • #troubleshooting
  • #errors
  • #tls

Exact Error Message

This error appears when the SSL channel is torn down before or during the handshake, most often because a plaintext client connected to an SSL listener:

[2026-06-29 07:55:23,118] ERROR [Producer clientId=clicks-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.SSLException: SSL channel closed
    at org.apache.kafka.common.network.SslTransportLayer.handshake

On the broker, an inbound plaintext connection to the SSL listener logs the mirror condition:

[2026-06-29 07:55:23,090] WARN [SocketServer listenerType=ZK_BROKER] Failed to send
SSL Close message (org.apache.kafka.common.network.SslTransportLayer)
java.io.IOException: Connection reset by peer

Related variants include “SSL channel closed”, “Failed to send SSL Close message”, “Connection reset by peer” during handshake, and SslAuthenticationException with no underlying alert.

What the Error Means

“SSL channel closed” / “Failed to send SSL Close message” means the TLS transport was closed abruptly rather than completing a clean handshake or a graceful close-notify. Unlike handshake_failure (an explicit negotiation rejection), PKIX path building failed (a trust decision), or CertificateExpiredException (a validity check), this is the absence of a proper TLS conversation — one side got bytes it could not interpret as TLS, or the socket dropped mid-handshake.

The dominant cause is protocol confusion: a client configured for PLAINTEXT (or pointed at the wrong port) connects to an SSL/SASL_SSL listener. The broker expects a TLS ClientHello but receives raw Kafka/plaintext bytes, so the channel is closed with no usable alert. The reverse — an SSL client hitting a plaintext listener — produces a similar abrupt close. Proxies and load balancers that terminate or mangle TLS can produce the same symptom.

Common Causes

  • Plaintext client to an SSL listener: security.protocol=PLAINTEXT (or unset) against port 9093/9094. The most common cause.
  • Wrong port: connecting to the SSL port with a plaintext config, or the plaintext port with an SSL config.
  • security.protocol mismatch with the listener’s configured protocol (SSL vs SASL_SSL vs PLAINTEXT).
  • Load balancer / proxy terminating TLS, health-checking with plaintext, or resetting idle connections mid-handshake.
  • Abrupt network drop: firewall idle-timeout or NAT resetting the socket during the handshake.
  • advertised.listeners protocol mismatch so clients reach a listener whose security protocol differs from their config.

How to Reproduce the Error

Point a plaintext client at the SSL listener:

cat > /tmp/plaintext-client.properties <<'EOF'
security.protocol=PLAINTEXT
EOF

kafka-broker-api-versions.sh --bootstrap-server broker-01.kafka.internal:9093 \
  --command-config /tmp/plaintext-client.properties

Because 9093 is an SSL listener, the broker receives non-TLS bytes and the connection is torn down, surfacing as SslAuthenticationException / “SSL channel closed” on a properly configured client, or a hang/reset on the plaintext one.

Diagnostic Commands

All commands below are read-only.

# Map each listener to its security protocol
grep -E 'listeners|advertised.listeners|listener.security.protocol.map' \
  /etc/kafka/server.properties
# Does the target port actually speak TLS? A clean handshake means it is an SSL listener
openssl s_client -connect broker-01.kafka.internal:9093 </dev/null 2>&1 | \
  grep -E 'Protocol|Cipher|Verify return code'
# Confirm the client's configured protocol and target port
grep -E 'security.protocol|bootstrap' /tmp/plaintext-client.properties
# Broker-side evidence of abrupt close / reset
sudo journalctl -u kafka --since "20 min ago" | \
  grep -iE "SSL channel closed|Failed to send SSL Close|Connection reset"
# Are intermediaries (LB/proxy) involved? Check what is actually listening
sudo ss -ltnp | grep -E ':9092|:9093|:9094'

If openssl s_client completes a handshake on the port but your client config says PLAINTEXT, the protocol mismatch is confirmed.

Step-by-Step Resolution

  1. Confirm it is a transport/protocol mismatch, not negotiation, trust, or expiry. “SSL channel closed” / “Failed to send SSL Close” indicates an abrupt close, not a TLS alert.
  2. Check the listener map. listener.security.protocol.map and listeners tell you whether the port is SSL, SASL_SSL, or PLAINTEXT.
  3. Probe the port with openssl s_client. A clean handshake means it is a TLS listener; your client must use security.protocol=SSL (or SASL_SSL).
  4. Align the client. Set the correct security.protocol and target the matching port; remove any leftover PLAINTEXT config.
  5. Verify advertised.listeners returns endpoints whose protocol matches what clients expect, so metadata-driven reconnects do not hit the wrong protocol.
  6. Rule out intermediaries. If a load balancer/proxy is between client and broker, confirm it passes TLS through (or terminates it correctly) and is not health-checking with plaintext or resetting idle sockets.
  7. Retry with kafka-broker-api-versions.sh using the corrected protocol.

Prevention and Best Practices

  • Keep listener-to-protocol mapping explicit and documented; never let a client default to PLAINTEXT against a secured port.
  • Validate security.protocol and port together in client config checks so a mismatched pair is rejected before deploy.
  • Ensure advertised.listeners protocols match the actual listeners to avoid reconnect-time mismatches.
  • For load balancers, use TCP passthrough for TLS (or correct termination) and exclude plaintext health checks from TLS ports.
  • Add an openssl s_client synthetic probe per port to assert it speaks the expected protocol. The free incident assistant can correlate “SSL channel closed” with a plaintext-to-SSL mismatch.
  • SSLHandshakeException: handshake_failure — an explicit negotiation rejection, not an abrupt close.
  • PKIX path building failed — a trust-chain failure after a real handshake.
  • CertificateExpiredException — a trusted chain with an expired cert.
  • No subject alternative names found — hostname verification after a successful handshake.

Frequently Asked Questions

What does “Failed to send SSL Close message” mean? The broker tried to gracefully close a TLS channel but the peer had already dropped it — typically because the peer was not speaking TLS at all (plaintext client to an SSL port).

Why is this different from handshake_failure? handshake_failure is an explicit TLS alert over protocol/cipher. “SSL channel closed” is an abrupt teardown with no usable alert, usually a protocol/port mismatch or a reset.

My config looks right but it still drops. What else? Suspect an intermediary: a load balancer terminating TLS, a plaintext health check on the TLS port, or a firewall/NAT resetting the connection mid-handshake.

How do I prove the port is TLS? Run openssl s_client -connect host:9093. A completed handshake with a Protocol/Cipher line means it is an SSL listener and the client must use security.protocol=SSL.

Can a wrong port cause this? Yes. Pointing an SSL client at the plaintext port (or a plaintext client at the SSL port) produces an abrupt close that surfaces as this error.

Free download · 368-page PDF

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.