{"id":"16d3f5c15a746c80","repo":"go-sql-driver/mysql","slug":"illegal-time-length-d","errorCode":null,"errorMessage":"illegal TIME length %d","messagePattern":"illegal TIME length (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"utils.go","lineNumber":460,"sourceCode":"\t\tdigits10[p3], digits01[p3],\n\t)\n\treturn appendMicrosecs(dst, src[2:], int(length)-20), nil\n}\n\nfunc 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])","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/c426bd93799de0f0e094c8f0582872c529d0ed0a/utils.go#L442-L478","documentation":"Thrown by formatBinaryTime (utils.go:460) when the DECLARED length of a binary TIME column is not in {8, 10, 11, 12, 13, 14, 15} — the legal binary TIME lengths (8 bytes base, plus fractional-second bytes). MySQL TIME can be negative or exceed 24h, and the driver only knows how to render these specific declared lengths.","triggerScenarios":"Scanning a MySQL TIME column from a binary-protocol row whose column metadata declares an unsupported length — corrupted column definition, non-MySQL server, or packet mangling. Fires during Scan on prepared-statement rows that touch a TIME column.","commonSituations":"A buggy proxy/router rewriting binary result metadata; a non-conforming MySQL fork; version skew; rare buffer corruption. The message reports the offending declared length.","solutions":["Inspect the column with SHOW COLUMNS / DESCRIBE and confirm it is a TIME type with a sane fractional precision.","Reproduce against the text protocol (CAST(col AS CHAR) or plain Query without ?) to isolate binary-path corruption.","Bypass proxies/tunnels and connect directly to MySQL.","If reproducible on vanilla MySQL, report upstream with the length value and column DDL."],"exampleFix":"// before\nvar d time.Duration\ndb.QueryRow(\"SELECT elapsed FROM t WHERE id=?\", id).Scan(&d)\n\n// after\nvar raw string\nif err := db.QueryRow(\"SELECT CAST(elapsed AS CHAR) FROM t WHERE id=?\", id).Scan(&raw); err == nil {\n    // parse 'HH:MM:SS' or '-HH:MM:SS' into a duration manually\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := rows.Scan(...); err != nil {\n    if strings.Contains(err.Error(), \"illegal TIME length\") {\n        // declared TIME length unsupported; read via CAST AS CHAR\n    }\n}","preventionTips":["Confirm TIME columns have a standard fractional precision via SHOW COLUMNS.","Bypass proxies/routers that rewrite binary column metadata.","Reproduce against a direct MySQL connection before assuming driver/server bugs."],"tags":["time","binary-protocol","wire-format","prepared-statement"],"analyzedSha":"c426bd93799de0f0e094c8f0582872c529d0ed0a","analyzedAt":"2026-08-04T21:52:59.219Z","schemaVersion":2}