go-sql-driver/mysql · critical

unsupported protocol version %d. Version %d or higher is req

Error message

unsupported protocol version %d. Version %d or higher is required

What it means

Returned during the initial handshake (packets.go:197) when the server's first byte (protocol version) is less than 10 (minProtocolVersion, const.go:18). Protocol 10 is the current standard used by all modern MySQL/MariaDB servers, so a lower value means the endpoint is not a real MySQL server or is impossibly ancient. The driver cannot proceed.

Source

Thrown at packets.go:197

******************************************************************************/

// Handshake Initialization Packet
// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_v10.html
// https://mariadb.com/kb/en/connection/#initial-handshake-packet
func (mc *mysqlConn) readHandshakePacket() (data []byte, capabilities capabilityFlag, extendedCapabilities extendedCapabilityFlag, plugin string, err error) {
	data, err = mc.readPacket()
	if err != nil {
		return
	}

	if data[0] == iERR {
		err = mc.handleErrorPacket(data)
		return
	}

	// protocol version [1 byte]
	if data[0] < minProtocolVersion {
		return nil, 0, 0, "", fmt.Errorf(
			"unsupported protocol version %d. Version %d or higher is required",
			data[0],
			minProtocolVersion,
		)
	}

	// server version [null terminated string]
	// connection id [4 bytes]
	pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4

	// first part of the password cipher [8 bytes]
	authData := data[pos : pos+8]

	// (filler) always 0x00 [1 byte]
	pos += 8 + 1

	// capability flags (lower 2 bytes) [2 bytes]
	capabilities = capabilityFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))

View on GitHub (pinned to c426bd9379)

Solutions

  1. Verify the DSN host/port point at a real MySQL/MariaDB server.
  2. Confirm connectivity from the same host using the mysql CLI client.
  3. Ensure no proxy/load-balancer is intercepting or misrouting the connection.
  4. Confirm the backend is MySQL/MariaDB and not another database on the same port.

Example fix

// before — wrong port (e.g. Redis)
sql.Open("mysql", "user:pass@tcp(localhost:6379)/db")

// after
sql.Open("mysql", "user:pass@tcp(localhost:3306)/db")
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check that the endpoint speaks MySQL before opening the driver
conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil { return err }
banner := make([]byte, 1)
_, _ = conn.Read(banner)
conn.Close()
if banner[0] < 10 { return fmt.Errorf("endpoint %s is not a MySQL server", addr) }

Try / catch

if err := db.Ping(); err != nil {
    if strings.Contains(err.Error(), "unsupported protocol version") {
        // the endpoint is not MySQL; verify host/port and proxies
    }
}

Prevention

When it happens

Trigger: Dialing a TCP/unix address that is not a MySQL server (e.g. Redis on 6379, an HTTP/SSH port); a load balancer/proxy returning a non-MySQL banner; connecting to a pre-3.x MySQL server.

Common situations: Wrong host/port in the DSN; service discovery returns the wrong address; a sidecar (Envoy, HAProxy, ProxySQL) misroutes the connection; port-forward pointing at the wrong pod.

Related errors


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