apache/cassandra · error · ProtocolException

Invalid BATCH message type

Error message

Invalid BATCH message type 

What it means

ProtocolException from BatchMessage codec's toType helper when the BATCH type byte is not 0 (LOGGED), 1 (UNLOGGED), or 2 (COUNTER). decode validated query kinds but this byte denotes the batch kind itself; an out-of-range value means a malformed or newer-protocol frame the server cannot interpret.

Solutions

  1. Fix the producer to encode type as 0 (LOGGED), 1 (UNLOGGED), or 2 (COUNTER).
  2. Verify client/server compression settings match to rule out byte-shift corruption.
  3. Dump the raw frame bytes and compare against the native protocol v-spec BATCH layout.
  4. Use the java driver's BatchStatement API so the type byte is encoded correctly.

Example fix

// before
body.writeByte(3); // invalid batch type
// after
body.writeByte(0); // LOGGED (1=UNLOGGED, 2=COUNTER)
Defensive patterns

Strategy: validation

Validate before calling

// when hand-encoding a BATCH header
int typeFlag = batchType.ordinal(); // LOGGED=0, UNLOGGED=1, COUNTER=2
if (typeFlag < 0 || typeFlag > 2) throw new IllegalArgumentException("batch type must be 0-2");

Try / catch

try { batch(); } catch (ProtocolException e) { if (e.getMessage().contains("Invalid BATCH message type")) dumpAndInspectFrame(); }

Prevention

When it happens

Trigger: A BATCH frame whose header type byte is not 0/1/2 — sent by a buggy custom client, corrupted in transit due to compression/framing mismatch, or mangled by an intermediary.

Common situations: Hand-written protocol clients writing the wrong batch-type byte; byte-shift corruption from wrong compression negotiation; proxy/transformation middleware re-encoding frames incorrectly.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/d12cbb0931d4d92f. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/transport/messages/BatchMessage.java:130

                size += CBUtil.sizeOfValueListOfByteArrays(msg.values.get(i));
            }
            size += version.isSmallerThan(ProtocolVersion.V3)
                  ? CBUtil.sizeOfConsistencyLevel(msg.options.getConsistency())
                  : QueryOptions.codec.encodedSize(msg.options, version);
            return size;
        }

        private BatchStatement.Type toType(byte b)
        {
            if (b == 0)
                return BatchStatement.Type.LOGGED;
            else if (b == 1)
                return BatchStatement.Type.UNLOGGED;
            else if (b == 2)
                return BatchStatement.Type.COUNTER;
            else
                throw new ProtocolException("Invalid BATCH message type " + b);
        }

        private byte fromType(BatchStatement.Type type)
        {
            switch (type)
            {
                case LOGGED:   return 0;
                case UNLOGGED: return 1;
                case COUNTER:  return 2;
                default:
                    throw new AssertionError();
            }
        }
    };

    public final BatchStatement.Type batchType;
    public final List<Object> queryOrIdList;
    public final List<byte[][]> values;

View on GitHub (pinned to 88fd0f6a0e)