shadow1ng/fscan · error

cassandra error: %s

Error message

cassandra error: %s

What it means

During the Cassandra native-protocol handshake, the server replied with an ERROR frame (opcode cqlOpError) in response to the OPTIONS/STARTUP exchange. The raw server error message is wrapped as 'cassandra error: %s' and returned as an auth failure (ErrorTypeAuth).

Source

Thrown at plugins/services/cassandra.go:120

	// Step 1: STARTUP (CQL_VERSION=3.0.0)
	startupBody := cqlStringMap(map[string]string{"CQL_VERSION": "3.0.0"})
	if err := cqlSend(conn, cqlOpStartup, startupBody); err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}

	// Step 2: 读取响应
	opcode, body, err := cqlRecv(conn)
	if err != nil {
		state.IncrementTCPFailedPacketCount()
		return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
	}

	// READY → 已就绪,发送测试查询
	// AUTHENTICATE → 需要认证
	// ERROR → 错误
	if opcode == cqlOpError {
		return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("cassandra error: %s", string(body))}
	}

	// Step 3: 如果需要认证
	if opcode == cqlOpAuthChl {
		if cred.Username == "" && cred.Password == "" {
			return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("authentication required")}
		}
		// SASL PLAIN: \x00username\x00password
		saslToken := []byte("\x00" + cred.Username + "\x00" + cred.Password)
		if err := cqlSend(conn, cqlOpAuthRsp, saslToken); err != nil {
			state.IncrementTCPFailedPacketCount()
			return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
		}
		opcode, body, err = cqlRecv(conn)
		if err != nil {
			state.IncrementTCPFailedPacketCount()
			return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
		}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Read the embedded server message from the error to identify the server-side cause (e.g. unsupported protocol version).
  2. Adjust the CQL protocol version used by the plugin to one supported by the target Cassandra release.
  3. Retry later or against another node if the server reports overload/unavailable.
Defensive patterns

Strategy: try-catch

Try / catch

res := doCassandraAuth(conn, cred, state)
if !res.Success && res.ErrorType == ErrorTypeAuth {
    var srvMsg string
    fmt.Sscanf(res.Error.Error(), "cassandra error: %s", &srvMsg)
    log.Printf("server rejected handshake: %s", srvMsg)
}

Prevention

When it happens

Trigger: doCassandraAuth sends the protocol STARTUP/OPTIONS frame and reads the reply; if the response opcode is cqlOpError, the server-side error body is surfaced via this error.

Common situations: Protocol version unsupported by the server; server rejecting the STARTUP options; node overloaded or bootstrapping; connecting to something that speaks CQL binary protocol but refuses the handshake.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/518050a34dabba91. Report an issue: GitHub.