{"record":{"id":"f2771d03901b89f6","repo":"go-sql-driver/mysql","slug":"year-is-not-in-the-range-1-9999-s","errorCode":null,"errorMessage":"year is not in the range [1, 9999]: %s","messagePattern":"year is not in the range \\[1, 9999\\]: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"utils.go","lineNumber":278,"sourceCode":"\t\t\tint(data[6]),                              // seconds\n\t\t\tint(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds\n\t\t\tloc,\n\t\t), nil\n\t}\n\treturn nil, fmt.Errorf(\"invalid DATETIME packet length %d\", num)\n}\n\nfunc appendDateTime(buf []byte, t time.Time, timeTruncate time.Duration) ([]byte, error) {\n\tif timeTruncate > 0 {\n\t\tt = t.Truncate(timeTruncate)\n\t}\n\n\tyear, month, day := t.Date()\n\thour, min, sec := t.Clock()\n\tnsec := t.Nanosecond()\n\n\tif year < 1 || year > 9999 {\n\t\treturn buf, errors.New(\"year is not in the range [1, 9999]: \" + strconv.Itoa(year)) // use errors.New instead of fmt.Errorf to avoid year escape to heap\n\t}\n\tyear100 := year / 100\n\tyear1 := year % 100\n\n\tvar localBuf [len(\"2006-01-02T15:04:05.999999999\")]byte // does not escape\n\tlocalBuf[0], localBuf[1], localBuf[2], localBuf[3] = digits10[year100], digits01[year100], digits10[year1], digits01[year1]\n\tlocalBuf[4] = '-'\n\tlocalBuf[5], localBuf[6] = digits10[month], digits01[month]\n\tlocalBuf[7] = '-'\n\tlocalBuf[8], localBuf[9] = digits10[day], digits01[day]\n\n\tif hour == 0 && min == 0 && sec == 0 && nsec == 0 {\n\t\treturn append(buf, localBuf[:10]...), nil\n\t}\n\n\tlocalBuf[10] = ' '\n\tlocalBuf[11], localBuf[12] = digits10[hour], digits01[hour]\n\tlocalBuf[13] = ':'","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/utils.go#L260-L296","documentation":"Returned by appendDateTime (utils.go:278) when serializing a time.Time to send to MySQL and the year is outside [1,9999]. MySQL's DATE/DATETIME types cannot represent year 0 or years >= 10000, so the driver refuses to format them. It is raised while building interpolated query arguments (connection.go:380) and binary protocol values (packets.go:1211).","triggerScenarios":"Binding a time.Time whose year is 0 (a non-zero-check zero value, or year 0001 which maps to Go year 1 boundary), or a far-future date (year >= 10000) as a query parameter that gets formatted via appendDateTime.","commonSituations":"Passing the zero time.Time (year 1) intending NULL but not using sql.NullTime; date arithmetic overflow; mock/test data with absurd years; a computed expiry date rolling past 9999.","solutions":["Send NULL for absent dates using sql.NullTime{Valid:false} or a nil *time.Time instead of time.Time{}.","Clamp/validate the year to [1,9999] before binding: reject or truncate out-of-range values.","Fix the upstream computation producing year 0 or year >= 10000.","For genuine out-of-range dates, store as a string column and format yourself."],"exampleFix":"// before: zero time.Time (year 1) intended as 'no date'\ndb.Exec(\"INSERT INTO t(d) VALUES(?)\", time.Time{})\n// -> \"year is not in the range [1, 9999]: 1\" on some paths / far-future overflow\n\n// after: express absence as NULL\nvar d sql.NullTime // Valid: false -> NULL\ndb.Exec(\"INSERT INTO t(d) VALUES(?)\", d)","handlingStrategy":"validation","validationCode":"// Validate a time.Time before binding it as a MySQL temporal value.\nfunc validForMySQL(t time.Time) bool {\n    y := t.Year()\n    return y >= 1 && y <= 9999\n}","typeGuard":"func isYearOutOfRange(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"year is not in the range [1, 9999]\")\n}","tryCatchPattern":"if !validForMySQL(t) {\n    // send NULL instead, or clamp/fix the value before binding\n    arg := sql.NullTime{}\n    db.ExecContext(ctx, \"INSERT INTO t(d) VALUES(?)\", arg)\n}","preventionTips":["Use sql.NullTime (or *time.Time) to represent absent dates instead of time.Time{}.","Range-check user/computed dates before persisting.","Watch for date-overflow arithmetic near year 9999."],"tags":["datetime","validation","data-binding"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}