go-sql-driver/mysql · critical
protocol error, illegal decimals value
Error message
protocol error, illegal decimals value %d
What it means
While decoding binary-protocol result rows, the column metadata's 'decimals' byte for TIME columns must be 0, 0x1f, or 1-6. A value outside that range (e.g. 7-30, or 31 other than 0x1f) means the packet is corrupt or non-conformant, so the driver aborts with this protocol error.
Solutions
- Retry the query once (transient corruption often does not recur).
- If reproducible, verify the server/proxy is MySQL-protocol-conformant and update or replace it.
- Check network/TLS/MTU health and packet integrity; capture a packet trace if it persists.
- Report upstream with the decimals value if it reproduces against a compliant server.
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
// No caller-side validation possible; this is a wire-integrity check. Best mitigation: // use TLS and keep the server/proxy on supported, conformant versions.
Type guard
null
Try / catch
// Treat as transient/protocol failure; retry with backoff, then surface.
if err := rows.Scan(...); err != nil && strings.Contains(err.Error(), "illegal decimals") {
// retry once; if it persists, investigate server/proxy/network
} Prevention
- Use TLS to prevent tampering/corruption on the wire.
- Keep the server and any proxy on MySQL-protocol-conformant versions.
- Implement a bounded retry for transient protocol errors.
When it happens
Trigger: A malformed/corrupted packet from the server or an intermediary; a buggy or non-MySQL-compatible proxy mangling the column metadata; transient memory/network corruption. Extremely rare with compliant servers.
Common situations: Flaky network, a non-conforming proxy or MySQL fork, or hardware corruption on the wire; intermittent and hard to reproduce.
Related errors
- unknown field type
- unsupported protocol version
- argument count mismatch
- can't convert %T to time.Time
- cannot convert type: %T
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/86250a91a80494fa.
Report an issue: GitHub.
Appendix: source
Thrown at packets.go:1409
fieldTypeTimestamp, fieldTypeDateTime: // Timestamp YYYY-MM-DD HH:MM:SS[.fractal]
num, isNull, n := readLengthEncodedInteger(data[pos:])
pos += n
switch {
case isNull:
dest[i] = nil
continue
case rows.rs.columns[i].fieldType == fieldTypeTime:
// database/sql does not support an equivalent to TIME, return a string
var dstlen uint8
switch decimals := rows.rs.columns[i].decimals; decimals {
case 0x00, 0x1f:
dstlen = 8
case 1, 2, 3, 4, 5, 6:
dstlen = 8 + 1 + decimals
default:
return fmt.Errorf(
"protocol error, illegal decimals value %d",
rows.rs.columns[i].decimals,
)
}
dest[i], err = formatBinaryTime(data[pos:pos+int(num)], dstlen)
case rows.mc.parseTime:
dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
default:
var dstlen uint8
if rows.rs.columns[i].fieldType == fieldTypeDate {
dstlen = 10
} else {
switch decimals := rows.rs.columns[i].decimals; decimals {
case 0x00, 0x1f:
dstlen = 19
case 1, 2, 3, 4, 5, 6:
dstlen = 19 + 1 + decimals
default:View on GitHub (pinned to 03d76c7e07)