apache/cassandra · error · org.apache.cassandra.transport.ProtocolException
Received frame with CUSTOM_PAYLOAD flag for native protocol
Error message
Received frame with CUSTOM_PAYLOAD flag for native protocol version < 4
What it means
ProtocolException thrown during message decoding when a frame carries the CUSTOM_PAYLOAD flag but the frame's native protocol version is older than V4, which introduced custom payloads. Older protocol versions cannot carry the trailing bytes-map that the flag promises, so the server rejects the frame as malformed. This is a strict version/feature compatibility check.
Source
Thrown at src/java/org/apache/cassandra/transport/Message.java:457
throw ErrorMessage.wrap(e, streamId);
}
}
abstract static class Decoder<M extends Message>
{
static Message decodeMessage(Channel channel, Envelope inbound)
{
boolean isRequest = inbound.header.type.direction == Direction.REQUEST;
boolean isTracing = inbound.header.hasFlag(Flag.TRACING);
boolean isCustomPayload = inbound.header.hasFlag(Flag.CUSTOM_PAYLOAD);
boolean hasWarning = inbound.header.hasFlag(Flag.WARNING);
TimeUUID tracingId = isRequest || !isTracing ? null : CBUtil.readTimeUUID(inbound.body);
List<String> warnings = isRequest || !hasWarning ? null : CBUtil.readStringList(inbound.body);
Map<String, ByteBuffer> customPayload = !isCustomPayload ? null : CBUtil.readBytesMap(inbound.body);
if (isCustomPayload && inbound.header.version.isSmallerThan(ProtocolVersion.V4))
throw new ProtocolException("Received frame with CUSTOM_PAYLOAD flag for native protocol version < 4");
Message message = inbound.header.type.codec.decode(inbound.body, inbound.header.version);
message.setSource(inbound);
message.setCustomPayload(customPayload);
if (isRequest)
{
assert message instanceof Request;
Request req = (Request) message;
Connection connection = channel.attr(Connection.attributeKey).get();
req.attach(connection);
if (isTracing)
req.setTracingRequested();
}
else
{
assert message instanceof Response;
if (isTracing)View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Raise the client's configured protocol version to V4 or higher (e.g. set protocolVersion to v4/v5 in the driver config).
- Update the driver to a modern version that only sets CUSTOM_PAYLOAD on V4+ connections.
- If the payload is not needed, remove the custom-payload option from the client configuration.
- Audit for mixed-version client libraries that hardcode flags independent of negotiated version.
Example fix
// before: client pinned to old protocol with custom payload enabled Cluster.builder().addContactPoint(host).withProtocolVersion(ProtocolVersion.V3).build(); // after: allow V4+ so CUSTOM_PAYLOAD is valid Cluster.builder().addContactPoint(host).withProtocolVersion(ProtocolVersion.V4).build();
Defensive patterns
Strategy: validation
Validate before calling
// check version/feature compatibility before enabling custom payloads if (chosenProtocolVersion < ProtocolVersion.V4) disableCustomPayload();
Try / catch
try { connect(); } catch (ProtocolException e) { if (e.getMessage().contains("CUSTOM_PAYLOAD")) { upgradeProtocolVersionOrDisablePayloads(); } } Prevention
- Keep drivers current so feature flags match negotiated protocol version
- Do not pin old protocol versions while using newer driver features
- Enable driver config validation in CI
When it happens
Trigger: A client (or driver) claims protocol v3 or lower in the frame header but sets the CUSTOM_PAYLOAD flag (0x04) in the frame's flags byte; decodeMessage in Message.Decoder detects version < V4 together with the flag.
Common situations: Driver misconfiguration pinning an old protocol version (e.g. protocolVersion: v3) while using a newer feature such as custom payloads for request tracing tags; mixing driver components of different versions; hand-rolled clients setting flags unconditionally.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Invalid message version. Got %s but previous messages on thi
- Invalid or unsupported protocol version (%d); supported vers
- native_transport_max_frame_size must be positive value < %dB
- Unknown code %d for a consistency level
- Wrong protocol direction (expected %s, got %s) for opcode %d
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5a9ac0d48fcbe68f.
Report an issue: GitHub.