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
- Check server/proxy compatibility and upgrade; capture the failing packet for analysis.
- Read the column as raw bytes ([]byte) or CAST to CHAR in SQL to avoid binary decoding.
- Switch the query to the text protocol (non-prepared) for the affected column.
- 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
- Restart the connection pool after packet errors to clear desync.
- Prefer text-protocol (CAST AS CHAR) for DATETIME through non-conforming servers.
- Upgrade/patch proxies that mishandle binary temporal values.
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
- illegal length
- invalid DATETIME packet length
- invalid TIME packet length
- illegal TIME length
- bad value for field: `%c`
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]...), nilView on GitHub (pinned to 03d76c7e07)