go-sql-driver/mysql · error
illegal %s length %d
Error message
illegal %s length %d
What it means
Thrown by formatBinaryDateTime (utils.go:404) when the DECLARED column length `length` is not in {10, 19, 21, 22, 23, 24, 25, 26} — the only legal text lengths for DATE (10) or DATETIME (19, or 19+fraction). The function builds the text representation of a binary DATE/DATETIME value and rejects lengths it cannot format. The interpolated type is 'DATE' or 'DATETIME'.
Source
Thrown at utils.go:404
}
func formatBinaryDateTime(src []byte, length uint8) (driver.Value, error) {
// length expects the deterministic length of the zero value,
// negative time and 100+ hours are automatically added if needed
if len(src) == 0 {
return zeroDateTime[:length], nil
}
var dst []byte // return value
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],View on GitHub (pinned to c426bd9379)
Solutions
- Reproduce with the text protocol (plain db.Query without placeholders, or CAST(col AS CHAR)) to isolate binary-protocol corruption.
- Bypass proxies/routers; connect directly to MySQL and confirm the column type/length with SHOW COLUMNS.
- Check the server is a genuine MySQL/MariaDB and is on a supported version.
- Report with the exact length value from the message if it reproduces against vanilla MySQL.
Example fix
// before
rows, _ := db.Query("SELECT d FROM t WHERE id=?", id)
// after: read as text for diagnosis
var s string
db.QueryRow("SELECT CAST(d AS CHAR) FROM t WHERE id=?", id).Scan(&s) Defensive patterns
Strategy: try-catch
Try / catch
if err := rows.Scan(...); err != nil {
if strings.Contains(err.Error(), "illegal ") && strings.Contains(err.Error(), "length") {
// declared column length is unsupported; read via CAST AS CHAR
}
} Prevention
- Verify DATE/DATETIME column definitions produce standard lengths with SHOW COLUMNS.
- Connect directly to MySQL to bypass proxies that rewrite column metadata.
- Keep the binary protocol path clean; report reproducible oddities upstream.
When it happens
Trigger: Result scanning a DATE/DATETIME column from a binary-protocol row where the column metadata's declared length is unexpected — e.g. a malformed binary result set, or a server/column definition with a non-standard length. Fires from Scan on prepared-statement rows.
Common situations: Corrupted binary row packets (flaky network, buggy proxy); a non-MySQL server advertising odd column lengths; version skew between client expectations and server; buffer corruption. Rare under normal operation.
Related errors
- invalid DATETIME packet length %d
- illegal %s packet 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/17ec3353208d0ef6.json.
Report an issue: GitHub.