go-sql-driver/mysql · critical

no Pem data found, data: %s

Error message

no Pem data found, data: %s

What it means

Thrown in the sha256_password auth path (auth.go:463) when pem.Decode on the server's authData returns no PEM block. Unlike caching_sha2_password, here the server is expected to send its RSA public key directly in the auth response; if those bytes aren't a valid PEM key, parsing fails. Note the capital 'P' — distinct string from error 54.

Source

Thrown at auth.go:463

					}
				}
				return mc.resultUnchanged().readResultOK()

			default:
				return ErrMalformPkt
			}
		default:
			return ErrMalformPkt
		}

	case "sha256_password":
		switch len(authData) {
		case 0:
			return nil // auth successful
		default:
			block, _ := pem.Decode(authData)
			if block == nil {
				return fmt.Errorf("no Pem data found, data: %s", authData)
			}

			pub, err := x509.ParsePKIXPublicKey(block.Bytes)
			if err != nil {
				return err
			}

			// send encrypted password
			err = mc.sendEncryptedPassword(oldAuthData, pub.(*rsa.PublicKey))
			if err != nil {
				return err
			}
			return mc.resultUnchanged().readResultOK()
		}

	default:
		return nil // auth successful
	}

View on GitHub (pinned to c426bd9379)

Solutions

  1. Enable TLS in the DSN so sha256_password uses cleartext over the encrypted channel and skips the key exchange.
  2. Inspect the %s bytes: if they resemble an error string, resolve the root auth failure first.
  3. Connect directly to MySQL, bypassing any proxy/router that may mangle the auth packet.
  4. Ensure the server is configured to provide its RSA public key (sha256_password_public_key_path / caching_sha2... server vars) if you must run without TLS.

Example fix

// before: sha256_password over plain TCP
// dsn := "user:pass@tcp(host:3306)/db"

// after: TLS removes the need for the key exchange
dsn := "user:pass@tcp(host:3306)/db?tls=skip-verify"
db, err := sql.Open("mysql", dsn)
Defensive patterns

Strategy: validation

Validate before calling

// for sha256_password, TLS removes the need to receive/parse the server key
func sha256SafeDSN(user, pass, host, db string) string {
    return fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=true", user, pass, host, db)
}

Try / catch

if err := db.PingContext(ctx); err != nil {
    if strings.Contains(err.Error(), "no Pem data found") {
        // enable TLS or unix socket and retry
    }
}

Prevention

When it happens

Trigger: Connecting to a server using the legacy sha256_password plugin over a non-TLS connection (the plugin requires RSA key exchange when TLS is absent), where the server's key payload is not parseable PEM — corrupted bytes, proxy mangling, or a non-conforming server.

Common situations: An older MySQL/MariaDB configured with sha256_password and no TLS; a proxy rewriting the auth payload; packet corruption; server configured to not advertise its key. The %s shows the offending bytes.

Related errors


AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04). Data as JSON: /data/errors/b8a4fdcd4abf5367.json. Report an issue: GitHub.