apache/cassandra · error · ProtocolException

Unexpected message , expecting

Error message

Unexpected message %s, expecting %s

What it means

A ProtocolException thrown when a message arrives while the connection is in the AUTHENTICATING stage but is neither AUTH_RESPONSE (SASL, protocol v2+) nor CREDENTIALS (legacy v1 auth). The server expects exactly one authentication message during this stage; anything else breaks the auth handshake and is rejected with an expectation message naming the correct type for the negotiated version.

Solutions

  1. Configure the client with the correct credentials so it responds with an AUTH_RESPONSE frame
  2. Match client auth settings to the server's authenticator (cassandra.yaml: authenticator class)
  3. On protocol v1, send CREDENTIALS instead of SASL_RESPONSE, or better, upgrade to a modern protocol version
  4. Fix driver state machines that skip the AUTHENTICATE wait step

Example fix

// before
cluster.init(); // no auth provider against PasswordAuthenticator server
// after
Cluster.builder().addContactPoint("127.0.0.1")
       .withCredentials("cassandra", "cassandra").build();
Defensive patterns

Strategy: validation

Validate before calling

if (serverRequiresAuth && credentials == null)
    throw new IllegalStateException("server authenticates; client must provide credentials to send AUTH_RESPONSE");

Type guard

boolean validAuthMessage(Message.Type t, ProtocolVersion v) { return v == ProtocolVersion.V1 ? t == Message.Type.CREDENTIALS : t == Message.Type.AUTH_RESPONSE; }

Try / catch

try { session = cluster.connect(); } catch (AuthenticationException | NoHostAvailableException e) { if (mentionsAuthHandshake(e)) applyCredentialsAndRetry(); else throw e; }

Prevention

When it happens

Trigger: During authentication (server sent AUTHENTICATE), client sends QUERY/STARTUP/OPTIONS or a malformed frame instead of AuthResponse (or Credentials on v1); validateNewMessage() rejects it with 'Unexpected message %s, expecting CREDENTIALS/SASL_RESPONSE'.

Common situations: Client without authentication configured connecting to an auth-required cluster, wrong authenticator mismatch between client and server (PasswordAuthenticator vs AllowAllAuthenticator), custom drivers skipping the SASL exchange, or race in connection setup code.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/transport/ServerConnection.java:90

    }

    ConnectionStage stage()
    {
        return stage;
    }

    QueryState validateNewMessage(Message.Type type, ProtocolVersion version)
    {
        switch (stage)
        {
            case ESTABLISHED:
                if (type != Message.Type.STARTUP && type != Message.Type.OPTIONS)
                    throw new ProtocolException(String.format("Unexpected message %s, expecting STARTUP or OPTIONS", type));
                break;
            case AUTHENTICATING:
                // Support both SASL auth from protocol v2 and the older style Credentials auth from v1
                if (type != Message.Type.AUTH_RESPONSE && type != Message.Type.CREDENTIALS)
                    throw new ProtocolException(String.format("Unexpected message %s, expecting %s", type, version == ProtocolVersion.V1 ? "CREDENTIALS" : "SASL_RESPONSE"));
                break;
            case READY:
                if (type == Message.Type.STARTUP)
                    throw new ProtocolException("Unexpected message STARTUP, the connection is already initialized");
                break;
            default:
                throw new AssertionError();
        }

        return new QueryState(clientState);
    }

    void applyStateTransition(Message.Type requestType, Message.Type responseType)
    {
        switch (stage)
        {
            case ESTABLISHED:
                if (requestType == Message.Type.STARTUP)

View on GitHub (pinned to 88fd0f6a0e)