go-sql-driver/mysql · error
illegal %s packet length %d
Error message
illegal %s packet length %d
What it means
Thrown by formatBinaryDateTime (utils.go:413) when the ACTUAL payload byte length `len(src)` is not one of {4, 7, 11} — the only valid binary DATE/DATETIME payload sizes (date / date+time / date+time+micros). Distinct from error 47 which checks the declared column length; this checks the real bytes received.
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 c426bd9379)
Solutions
- Note the actual length in the message and reproduce with the text protocol (CAST AS CHAR) to confirm whether the binary path is the culprit.
- Eliminate proxies/tunnels; connect directly to MySQL and retry the prepared statement.
- Verify server version and column type with SHOW COLUMNS.
- If it reproduces against vanilla MySQL, report upstream with the length value and column DDL.
Example fix
// before
var t time.Time
db.QueryRow("SELECT d FROM t WHERE id=?", id).Scan(&t)
// after
var raw string
if err := db.QueryRow("SELECT CAST(d AS CHAR) FROM t WHERE id=?", id).Scan(&raw); err == nil {
t, err = time.ParseInLocation("2006-01-02 15:04:05", raw, time.Local)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := rows.Scan(...); err != nil {
if strings.Contains(err.Error(), "illegal ") && strings.Contains(err.Error(), "packet length") {
// actual binary payload size is wrong; fall back to text protocol
}
} Prevention
- For corrupted binary-row environments, force the text protocol via CAST AS CHAR or plain Query.
- Remove proxies/routers that truncate binary datetime payloads.
- Monitor network health to catch truncation early.
When it happens
Trigger: Reading a DATE/DATETIME column via the binary protocol where the actual bytes in the row packet don't match a valid payload size — truncated packets, padding corruption, or a non-conforming server. Fires during Scan on prepared-statement rows.
Common situations: Truncated/corrupted binary row packets over a flaky link; a proxy/router that mishandles binary datetime payloads; server-version mismatch; rare memory corruption. The message reports the actual (invalid) byte count.
Related errors
- invalid DATETIME packet length %d
- illegal %s length %d
- illegal TIME length %d
- invalid TIME packet length %d
- invalid time bytes: %s
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/7e1f26b5f1a33d2a.json.
Report an issue: GitHub.