go-sql-driver/mysql · error

unexpected read from socket

Error message

unexpected read from socket

What it means

Error "unexpected read from socket" thrown in go-sql-driver/mysql.

Source

Thrown at conncheck.go:20

//
// Copyright 2019 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

//go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || illumos

package mysql

import (
	"errors"
	"io"
	"net"
	"syscall"
)

var errUnexpectedRead = errors.New("unexpected read from socket")

func connCheck(conn net.Conn) error {
	var sysErr error

	sysConn, ok := conn.(syscall.Conn)
	if !ok {
		return nil
	}
	rawConn, err := sysConn.SyscallConn()
	if err != nil {
		return err
	}

	err = rawConn.Read(func(fd uintptr) bool {
		var buf [1]byte
		n, err := syscall.Read(int(fd), buf[:])
		switch {
		case n == 0 && err == nil:

View on GitHub (pinned to 03d76c7e07)

Solutions

  1. Check that the remote MySQL server or proxy is not writing unexpected data to the connection; this usually indicates a broken or hijacked TCP connection, so reconnect and retry the operation.
  2. Verify that no intermediary (proxy, load balancer, or middleware) is injecting bytes into the socket, and that the connection is a genuine MySQL protocol connection.
  3. Avoid sharing a single connection across goroutines outside database/sql semantics; let database/sql manage connection pooling and recreate the connection if it becomes invalid.

Example fix

// Recreate the connection instead of reusing a corrupted one
db, err := sql.Open("mysql", dsn)
if err != nil {
    return err
}
if err := db.Ping(); err != nil {
    db.Close()
    db, err = sql.Open("mysql", dsn) // retry with a fresh connection
}

When it happens

Trigger: The driver performs a non-destructive readability check on the raw socket (via syscall.RawConn and a peek read) before handing the connection to the pool, and the kernel reports pending data or an error on a connection that should be idle.

Common situations: Typically happens when the server (or a proxy/middlebox) sent unexpected bytes on an idle pooled connection, or the connection was half-closed. The driver discards the connection and retries on a fresh one, so it is usually transient; frequent occurrences point to network middleboxes killing idle connections or a mismatched wait_timeout.


AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07). Data as JSON: /api/errors/cf6c1f790310d7ee. Report an issue: GitHub.