{"record":{"id":"1a9f2b70fb1d0153","repo":"apache/cassandra","slug":"unexpected-message-s-expecting-s","errorCode":null,"errorMessage":"Unexpected message %s, expecting %s","messagePattern":"Unexpected message (.+?), expecting (.+?)","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/transport/ServerConnection.java","lineNumber":90,"sourceCode":"    }\n\n    ConnectionStage stage()\n    {\n        return stage;\n    }\n\n    QueryState validateNewMessage(Message.Type type, ProtocolVersion version)\n    {\n        switch (stage)\n        {\n            case ESTABLISHED:\n                if (type != Message.Type.STARTUP && type != Message.Type.OPTIONS)\n                    throw new ProtocolException(String.format(\"Unexpected message %s, expecting STARTUP or OPTIONS\", type));\n                break;\n            case AUTHENTICATING:\n                // Support both SASL auth from protocol v2 and the older style Credentials auth from v1\n                if (type != Message.Type.AUTH_RESPONSE && type != Message.Type.CREDENTIALS)\n                    throw new ProtocolException(String.format(\"Unexpected message %s, expecting %s\", type, version == ProtocolVersion.V1 ? \"CREDENTIALS\" : \"SASL_RESPONSE\"));\n                break;\n            case READY:\n                if (type == Message.Type.STARTUP)\n                    throw new ProtocolException(\"Unexpected message STARTUP, the connection is already initialized\");\n                break;\n            default:\n                throw new AssertionError();\n        }\n\n        return new QueryState(clientState);\n    }\n\n    void applyStateTransition(Message.Type requestType, Message.Type responseType)\n    {\n        switch (stage)\n        {\n            case ESTABLISHED:\n                if (requestType == Message.Type.STARTUP)","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/transport/ServerConnection.java#L72-L108","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Configure the client with the correct credentials so it responds with an AUTH_RESPONSE frame","Match client auth settings to the server's authenticator (cassandra.yaml: authenticator class)","On protocol v1, send CREDENTIALS instead of SASL_RESPONSE, or better, upgrade to a modern protocol version","Fix driver state machines that skip the AUTHENTICATE wait step"],"exampleFix":"// before\ncluster.init(); // no auth provider against PasswordAuthenticator server\n// after\nCluster.builder().addContactPoint(\"127.0.0.1\")\n       .withCredentials(\"cassandra\", \"cassandra\").build();","handlingStrategy":"validation","validationCode":"if (serverRequiresAuth && credentials == null)\n    throw new IllegalStateException(\"server authenticates; client must provide credentials to send AUTH_RESPONSE\");","typeGuard":"boolean validAuthMessage(Message.Type t, ProtocolVersion v) { return v == ProtocolVersion.V1 ? t == Message.Type.CREDENTIALS : t == Message.Type.AUTH_RESPONSE; }","tryCatchPattern":"try { session = cluster.connect(); } catch (AuthenticationException | NoHostAvailableException e) { if (mentionsAuthHandshake(e)) applyCredentialsAndRetry(); else throw e; }","preventionTips":["Keep client auth config in sync with server authenticator (cassandra.yaml)","Never connect without credentials when the server uses PasswordAuthenticator","Don't send queries while the connection is mid-authentication","Use protocol v2+ (SASL) instead of legacy v1 CREDENTIALS"],"tags":["cql-protocol","authentication","state-machine","handshake"],"backgroundTag":"authentication-required","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}