{"id":"f558e77f8fce7b43","repo":"go-sql-driver/mysql","slug":"invalid-time-packet-length-d","errorCode":null,"errorMessage":"invalid TIME packet length %d","messagePattern":"invalid TIME packet length (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"utils.go","lineNumber":465,"sourceCode":"func formatBinaryTime(src []byte, length uint8) (driver.Value, error) {\n\t// length expects the deterministic length of the zero value,\n\t// negative time and 100+ hours are automatically added if needed\n\tif len(src) == 0 {\n\t\treturn zeroDateTime[11 : 11+length], nil\n\t}\n\tvar dst []byte // return value\n\n\tswitch length {\n\tcase\n\t\t8,                      // time (can be up to 10 when negative and 100+ hours)\n\t\t10, 11, 12, 13, 14, 15: // time with fractional seconds\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"illegal TIME length %d\", length)\n\t}\n\tswitch len(src) {\n\tcase 8, 12:\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid TIME packet length %d\", len(src))\n\t}\n\t// +2 to enable negative time and 100+ hours\n\tdst = make([]byte, 0, length+2)\n\tif src[0] == 1 {\n\t\tdst = append(dst, '-')\n\t}\n\tdays := binary.LittleEndian.Uint32(src[1:5])\n\thours := int64(days)*24 + int64(src[5])\n\n\tif hours >= 100 {\n\t\tdst = strconv.AppendInt(dst, hours, 10)\n\t} else {\n\t\tdst = append(dst, digits10[hours], digits01[hours])\n\t}\n\n\tmin, sec := src[6], src[7]\n\tdst = append(dst, ':',\n\t\tdigits10[min], digits01[min], ':',","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/c426bd93799de0f0e094c8f0582872c529d0ed0a/utils.go#L447-L483","documentation":"Thrown by formatBinaryTime (utils.go:465) when the ACTUAL payload byte length of a binary TIME value is not in {8, 12} — the only valid binary TIME payload sizes (8 bytes without fraction, 12 with micros). Distinct from error 49 which checks the declared length; this checks the bytes actually received.","triggerScenarios":"Reading a TIME column via the binary protocol where the row packet's TIME payload has a byte count other than 8 or 12 — truncated packet, padding corruption, non-conforming server. Fires during Scan on prepared-statement rows touching a TIME column.","commonSituations":"Truncated/corrupted binary row data over a flaky network; a proxy/router mishandling binary TIME payloads; server-version mismatch; rare memory corruption. The message reports the actual invalid length.","solutions":["Note the actual length in the message; reproduce with the text protocol (CAST AS CHAR or plain Query) to confirm the binary path is at fault.","Connect directly to MySQL, bypassing any proxy/router/tunnel.","Verify the column type and server version with SHOW COLUMNS and SELECT VERSION().","Report upstream if it reproduces against vanilla MySQL, including the length and column DDL."],"exampleFix":"// before\nvar d time.Duration\ndb.QueryRow(\"SELECT elapsed FROM t WHERE id=?\", id).Scan(&d)\n\n// after: read text for diagnosis\nvar raw string\nif err := db.QueryRow(\"SELECT TIME_FORMAT(elapsed, '%H:%i:%s') FROM t WHERE id=?\", id).Scan(&raw); err == nil {\n    // parse manually\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := rows.Scan(...); err != nil {\n    if strings.Contains(err.Error(), \"invalid TIME packet length\") {\n        // binary TIME payload size wrong; fall back to text protocol\n    }\n}","preventionTips":["For flaky binary-row links, read TIME columns via TIME_FORMAT(...) or CAST AS CHAR (text protocol).","Eliminate network components that truncate binary TIME payloads.","Validate server version supports the binary TIME shapes you depend on."],"tags":["time","binary-protocol","wire-format","prepared-statement"],"analyzedSha":"c426bd93799de0f0e094c8f0582872c529d0ed0a","analyzedAt":"2026-08-04T21:52:59.219Z","schemaVersion":2}