go-sql-driver/mysql · error
unexpected resp from server for caching_sha2_password…
Error message
unexpected resp from server for caching_sha2_password, perform full authentication
What it means
Returned during caching_sha2_password full authentication over a non-TLS, non-unix connection (auth.go:426). The client requests the server's RSA public key and expects an AuthMoreData (0x01) frame; if the first byte of the response differs, the handshake is treated as broken.
Solutions
- Use TLS (tls=true) or a unix socket so the driver sends the password as cleartext and skips key exchange entirely.
- Pre-load the server's RSA public key via the DSN (serverPubKey=<name> registered with mysql.RegisterServerPubKey) to avoid requesting it dynamically.
- Remove any proxy that rewrites the auth handshake, or configure it to be fully transparent.
- Upgrade the server/proxy to a version that correctly implements caching_sha2_password full auth.
Example fix
// before: plaintext TCP, cold cache -> key-exchange desync
dsn := "user:pass@tcp(mysql8:3306)/db"
// after: TLS removes the need for the public-key exchange
dsn := "user:pass@tcp(mysql8:3306)/db?tls=true"
// or pin the key:
// mysql.RegisterServerPubKey("mysql8", pemBytes)
// dsn := "...?serverPubKey=mysql8" Defensive patterns
Strategy: retry
Validate before calling
// Avoid the dynamic key exchange entirely: prefer TLS/unix or pin the key.
if !tlsAvailable && serverPubKeyPEM == "" {
return errors.New("caching_sha2 over plaintext needs TLS or a pinned pubkey")
} Type guard
func isCachingSha2BadResp(err error) bool {
return err != nil && strings.Contains(err.Error(), "caching_sha2_password, perform full authentication")
} Try / catch
if isCachingSha2BadResp(err) {
// switch to TLS/unix, or pin serverPubKey, then retry the connection.
} Prevention
- Use tls=true or unix sockets for caching_sha2_password accounts.
- Pre-register the server key with mysql.RegisterServerPubKey and reference it via serverPubKey.
- Remove proxies that alter the auth-more-data handshake.
When it happens
Trigger: First (uncached) login of a caching_sha2_password user over plaintext TCP without a configured server public key, where the server's response is not the expected AuthMoreData frame — e.g. a proxy/MITM altering the handshake, a server bug, or stream corruption during key exchange.
Common situations: MySQL 8.0 default auth (caching_sha2_password) over unencrypted networks; a load balancer or connection-pooling proxy that doesn't pass through auth-more-data; first connection after server restart (cache cold).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- no pem data found, data
- no Pem data found, data
- this user requires clear text authentication. If you still…
- this user requires old password authentication. If you…
- TLS requested but server does not support TLS
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/fd4cceb256f1494b.
Report an issue: GitHub.
Appendix: source
Thrown at auth.go:426
pubKey := mc.cfg.pubKey
if pubKey == nil {
// request public key from server
data, err := mc.buf.takeSmallBuffer(4 + 1)
if err != nil {
return err
}
data[4] = cachingSha2PasswordRequestPublicKey
err = mc.writePacket(data)
if err != nil {
return err
}
if data, err = mc.readPacket(); err != nil {
return err
}
if data[0] != iAuthMoreData {
return fmt.Errorf("unexpected resp from server for caching_sha2_password, perform full authentication")
}
// parse public key
block, rest := pem.Decode(data[1:])
if block == nil {
return fmt.Errorf("no pem data found, data: %s", rest)
}
pkix, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
pubKey = pkix.(*rsa.PublicKey)
}
// send encrypted password
err = mc.sendEncryptedPassword(oldAuthData, pubKey)
if err != nil {
return errView on GitHub (pinned to 03d76c7e07)