{"record":{"id":"e674c43ac7ae2dd9","repo":"go-sql-driver/mysql","slug":"not-0-9","errorCode":null,"errorMessage":"not [0-9]","messagePattern":"not \\[0-9\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"utils.go","lineNumber":225,"sourceCode":"\nfunc parseByteNanoSec(b []byte) (int, error) {\n\tns, digit := 0, 100000 // max is 6-digits\n\tfor i := range b {\n\t\tv, err := bToi(b[i])\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tns += v * digit\n\t\tdigit /= 10\n\t}\n\t// nanoseconds has 10-digits. (needs to scale digits)\n\t// 10 - 6 = 4, so we have to multiple 1000.\n\treturn ns * 1000, nil\n}\n\nfunc bToi(b byte) (int, error) {\n\tif b < '0' || b > '9' {\n\t\treturn 0, errors.New(\"not [0-9]\")\n\t}\n\treturn int(b - '0'), nil\n}\n\nfunc parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {\n\tswitch num {\n\tcase 0:\n\t\treturn time.Time{}, nil\n\tcase 4:\n\t\treturn time.Date(\n\t\t\tint(binary.LittleEndian.Uint16(data[:2])), // year\n\t\t\ttime.Month(data[2]),                       // month\n\t\t\tint(data[3]),                              // day\n\t\t\t0, 0, 0, 0,\n\t\t\tloc,\n\t\t), nil\n\tcase 7:\n\t\treturn time.Date(","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/utils.go#L207-L243","documentation":"Returned by bToi (utils.go:225) when a byte is outside the ASCII range '0'..'9'. bToi is the low-level digit parser used by parseByteYear, parseByte2Digits and parseByteNanoSec, which in turn feed parseDateTime / parseBinaryDateTime when decoding DATE/DATETIME/TIMESTAMP values received from the server.","triggerScenarios":"Decoding a textual or binary temporal value whose digit fields contain non-numeric bytes — corrupted row data, a column reinterpreted as the wrong type, or data produced by a non-conformant server/proxy that mangled the datetime wire format.","commonSituations":"Reading a DATE/DATETIME column that was actually stored as malformed text; corrupt pages; a custom MySQL fork emitting non-standard datetime encodings; proxy rewriting payloads.","solutions":["Inspect the actual bytes in the offending column (SELECT HEX(col)) to confirm corruption vs. misinterpretation.","If the data is genuinely text, store/retrieve it as a string and parse with time.Parse yourself.","Repair or reload the corrupted rows; validate at insert time to prevent recurrence.","Ensure you are talking to a standards-compliant MySQL/MariaDB server, not a mangling proxy."],"exampleFix":"// before: column `d` holds malformed bytes; driver fails decoding\nvar t time.Time\nrow.Scan(&t) // -> \"not [0-9]\"\n\n// after: read raw and parse defensively\nvar raw string\nrow.Scan(&raw)\nt, err := time.ParseInLocation(\"2006-01-02 15:04:05\", raw, time.UTC)\nif err != nil { /* handle */ }","handlingStrategy":"fallback","validationCode":"// Scan temporal columns into a string first so corrupt encodings are\n// observable rather than fatal.\nvar raw sql.NullString\nif err := rows.Scan(&raw); err != nil { /* handle */ }\nt, err := time.ParseInLocation(\"2006-01-02 15:04:05\", raw.String, loc)","typeGuard":"func isNotDigitParse(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"not [0-9]\")\n}","tryCatchPattern":"var t time.Time\nif err := rows.Scan(&t); err != nil && isNotDigitParse(err) {\n    // column held non-numeric datetime bytes: scan as raw and parse\n    // defensively, or flag the row for repair.\n}","preventionTips":["Validate datetime strings at insert time.","Use SELECT HEX(col) to inspect suspect temporal data.","Don't reinterpret text columns as DATE/DATETIME in the schema."],"tags":["datetime","parsing","data-corruption"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}