go-sql-driver/mysql · error

illegal packet length

Error message

illegal %s packet length %d

What it means

Raised by formatBinaryDateTime (utils.go:413) for the actual PAYLOAD length. When formatting a binary DATE/DATETIME to text, the driver requires the received byte slice length to be exactly 4, 7, or 11 (DATE, DATETIME, DATETIME-with-fractional). Any other length indicates the server sent a malformed binary value or the read pointer is desynchronized.

Solutions

  1. Check server/proxy compatibility and upgrade; capture the failing packet for analysis.
  2. Read the column as raw bytes ([]byte) or CAST to CHAR in SQL to avoid binary decoding.
  3. Switch the query to the text protocol (non-prepared) for the affected column.
  4. Restart the connection pool to clear any desync state.

Example fix

-- force server-side text conversion
SELECT CAST(created_at AS CHAR) AS created_at FROM t WHERE id = ?;

// Go: scan into []byte / string
var s string
db.QueryRow(query, id).Scan(&s)
Defensive patterns

Strategy: try-catch

Validate before calling

// Payload length is server-controlled; no client-side pre-check exists.
// Mitigate by validating the server speaks the standard binary protocol.
func isStandardBinaryDatePacketLen(n int) bool {
    switch n {
    case 4, 7, 11:
        return true
    }
    return false
}

Type guard

func isStandardBinaryDatePacketLen(n int) bool {
    switch n {
    case 4, 7, 11:
        return true
    }
    return false
}

Try / catch

var s string
if err := db.QueryRow(q, id).Scan(&s); err != nil {
    if strings.Contains(err.Error(), "packet length") {
        var raw []byte
        _ = db.QueryRow(`SELECT CAST(col AS CHAR) FROM t WHERE id=?`, id).Scan(&raw)
        s = string(raw)
    }
}

Prevention

When it happens

Trigger: Reading DATE/DATETIME/TIMESTAMP via a prepared statement (parseTime=false) when the server returns a binary temporal value whose length is not 4/7/11. Reached via formatBinaryDateTime at packets.go:1434 with src = data[pos:pos+num]. Indicates packet desync, truncation, or a non-conforming MySQL-compatible server.

Common situations: Result-set desynchronization after an earlier packet parse error, a proxy that re-encodes temporal values incorrectly, network corruption, or an exotic server fork with non-standard binary DATETIME encoding.

Related errors


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

Appendix: source

Thrown at utils.go:413

	var p1, p2, p3 byte // current digit pair

	switch length {
	case 10, 19, 21, 22, 23, 24, 25, 26:
	default:
		t := "DATE"
		if length > 10 {
			t += "TIME"
		}
		return nil, fmt.Errorf("illegal %s length %d", t, length)
	}
	switch len(src) {
	case 4, 7, 11:
	default:
		t := "DATE"
		if length > 10 {
			t += "TIME"
		}
		return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
	}
	dst = make([]byte, 0, length)
	// start with the date
	year := binary.LittleEndian.Uint16(src[:2])
	pt := year / 100
	p1 = byte(year - 100*uint16(pt))
	p2, p3 = src[2], src[3]
	dst = append(dst,
		digits10[pt], digits01[pt],
		digits10[p1], digits01[p1], '-',
		digits10[p2], digits01[p2], '-',
		digits10[p3], digits01[p3],
	)
	if length == 10 {
		return dst, nil
	}
	if len(src) == 4 {
		return append(dst, zeroDateTime[10:length]...), nil

View on GitHub (pinned to 03d76c7e07)