apache/cassandra · warning
Failed to properly handshake with peer
Error message
Failed to properly handshake with peer {}. Closing the channel. Invalid legacy protocol magic. What it means
Logged when the Netty channel exception handler detects that a peer sent an internode handshake whose 'magic' value does not match any legacy protocol version Cassandra can speak. The connection is closed via failHandshake because the peer is either not a Cassandra node, runs a wildly incompatible major version, or is a non-Cassandra process on the internode port.
Solutions
- Verify both endpoints run compatible Cassandra versions for the cluster (roll upgrades within supported versions).
- Check that the peer really is a Cassandra node and that the address:storage_port is correct in cassandra.yaml.
- Inspect internode_error_reporting_exclusions and health-checkers: exclude LB/probe IPs that hit the storage port.
- Run nodetool gossipinfo / verify network connectivity and that no other service occupies storage_port.
- If the peer cannot be made compatible, firewall it off or stop it from connecting.
Defensive patterns
Strategy: validation
Validate before calling
// Before pointing any process at storage_port, verify it is a Cassandra peer: // nodetool gossipinfo | grep <peer-ip> // netstat -tlnp | grep 7000 (confirm only Cassandra binds the port)
Try / catch
// Server-side: this is logged, not thrown to user code. // Suppress noise from known non-Cassandra probes via cassandra.yaml: // internode_error_reporting_exclusions: [<lb-ip>, <probe-ip>]
Prevention
- Never point native-transport clients or health checks at storage_port.
- Keep cluster versions within supported upgrade compatibility.
- Exclude load-balancer/probe IPs via internode_error_reporting_exclusions.
- Monitor this warning to detect rogue services on the internode port.
When it happens
Trigger: exceptionCaught fires with a root cause of Message.InvalidLegacyProtocolMagic during the internode connection handshake; happens when a peer connects that cannot deserialize the initial handshake frame.
Common situations: Misconfigured clients pointed at the storage_port (e.g. a client using native transport port as internode), mixed-version clusters crossing incompatible majors, firewalls/proxies or load balancers health-checking the internode port, or a non-Cassandra service bound to the same port.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Addresses differ: !=
- broadcast_address cannot be a wildcard address (
- Configured " " caused an exception
- Configured " " could not be found
- Configured " " was found, but had no addresses
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/1a3e4f438ff07b39.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/net/InboundConnectionInitiator.java:396
{
return ctx.pipeline().get(SslHandler.class) != null;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
{
exceptionCaught(ctx.channel(), cause);
}
private void exceptionCaught(Channel channel, Throwable cause)
{
final SocketAddress remoteAddress = channel.remoteAddress();
boolean reportingExclusion = DatabaseDescriptor.getInternodeErrorReportingExclusions().contains(remoteAddress);
if (reportingExclusion)
logger.debug("Excluding internode exception for {}; address contained in internode_error_reporting_exclusions", remoteAddress, cause);
else if (cause != null && Throwables.getRootCause(cause) instanceof Message.InvalidLegacyProtocolMagic && DatabaseDescriptor.getInvalidLegacyProtocolMagicNoSpamEnabled())
noSpam5m.warn("Failed to properly handshake with peer {}. Closing the channel. Invalid legacy protocol magic.", ((InetSocketAddress) channel.remoteAddress()).getHostName());
else
logger.error("Failed to properly handshake with peer {}. Closing the channel.", remoteAddress, cause);
try
{
failHandshake(channel);
}
catch (Throwable t)
{
if (!reportingExclusion)
logger.error("Unexpected exception in {}.exceptionCaught", this.getClass().getSimpleName(), t);
}
}
private void failHandshake(ChannelHandlerContext ctx)
{
failHandshake(ctx.channel());
}View on GitHub (pinned to 88fd0f6a0e)