shadow1ng/fscan · error
SASL handshake error: %d
Error message
SASL handshake error: %d
What it means
doKafkaAuth parses the SaslHandshake response and reads the first 2 bytes as a big-endian int16 error_code. A non-zero code means the broker rejected the handshake (unknown mechanism, unsupported SASL version, auth disabled, security protocol mismatch). The numeric Kafka protocol error code is embedded in the message for diagnosis.
Source
Thrown at plugins/services/kafka.go:113
// Step 2: SASL/PLAIN 认证 (如果需要)
if cred.Username != "" || cred.Password != "" {
// SaslHandshake: mechanism=PLAIN (api_key=17, api_version=0)
body := kafkaString("PLAIN")
if err := kafkaSend(conn, 17, 0, body); err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
}
resp, err := kafkaRecv(conn)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{Success: false, ErrorType: classifyKafkaErrorType(err), Error: err}
}
// SaslHandshake 响应: [4B error_code] + [mechanisms array]
if len(resp) >= 2 {
code := int16(binary.BigEndian.Uint16(resp[:2]))
if code != 0 {
return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("SASL handshake error: %d", code)}
}
}
// SaslAuthenticate: PLAIN token = \x00user\x00pass (api_key=36, api_version=0)
token := []byte("\x00" + cred.Username + "\x00" + cred.Password)
authBody := kafkaBytes(token)
if err := kafkaSend(conn, 36, 0, authBody); err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{Success: false, ErrorType: ErrorTypeNetwork, Error: err}
}
resp, err = kafkaRecv(conn)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{Success: false, ErrorType: classifyKafkaErrorType(err), Error: err}
}
if len(resp) >= 2 {
code := int16(binary.BigEndian.Uint16(resp[:2]))
if code != 0 {View on GitHub (pinned to 95cc12e753)
Solutions
- Match the security protocol: use TLS for SASL_SSL listeners before attempting SASL
- Verify the broker listener supports the PLAIN mechanism (check sasl.enabled.mechanisms)
- Decode the specific code (e.g. 33=UnsupportedSaslMechanism, 34=IllegalSaslState) to target the fix
- Confirm the broker's listener port is the SASL-enabled one, not PLAINTEXT
Example fix
// before
if code != 0 {
return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("SASL handshake error: %d", code)}
}
// after
if code != 0 {
return &AuthResult{Success: false, ErrorType: ErrorTypeAuth, Error: fmt.Errorf("SASL handshake error: %d (%s)", code, kafkaSaslHandshakeErrText(code))}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Probe the listener's security protocol before SASL // e.g. send ApiVersions unencrypted; if the broker requires TLS the frame fails early
Type guard
func isHandshakeRejected(code int16) bool {
return code != 0 // 33 UnsupportedSaslMechanism, 34 IllegalSaslState
} Try / catch
res := plugin.Scan(info, config, state)
if a := res.AuthResults; a != nil {
for _, r := range a {
if r.Error != nil && strings.Contains(r.Error.Error(), "SASL handshake error") {
log.Printf("kafka: broker rejected handshake (%v); check listener protocol/mechanism", r.Error)
}
}
} Prevention
- Match plaintext vs SASL_SSL to the broker listener before authenticating
- Confirm PLAIN is in sasl.enabled.mechanisms (else use SCRAM)
- Decode Kafka protocol error codes (33/34) for targeted fixes
- Pin api_version supported by the broker version in use
When it happens
Trigger: doKafkaAuth: after sending the SaslHandshake request (api_key=17) over PLAIN, kafkaRecv returns a response whose first 2 bytes are a non-zero error code.
Common situations: Broker listener configured with SASL_SSL while plugin connects plaintext (or vice versa); broker does not support the PLAIN mechanism (only SCRAM); SASL not enabled on the listener at all; api_version mismatch with older brokers.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- SASL authenticate error: %d
- oracle authentication protocol internal error
- authentication required
- authentication failed: %s
- invalid kafka response length: %d
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/1358cf4560812bc3.
Report an issue: GitHub.