go-sql-driver/mysql · error
can't convert %T to time.Time
Error message
can't convert %T to time.Time
What it means
Returned by the deprecated NullTime.Scan (nulltime.go:62) when the scanned value is not time.Time, []byte, or string. NullTime is deprecated in favor of sql.NullTime; its Scan only accepts those three types and interprets times as UTC, ignoring the loc DSN parameter. Any other concrete type (e.g. an int64 epoch value) reaches the final fmt.Errorf.
Source
Thrown at nulltime.go:62
return
}
switch v := value.(type) {
case time.Time:
nt.Time, nt.Valid = v, true
return
case []byte:
nt.Time, err = parseDateTime(v, time.UTC)
nt.Valid = (err == nil)
return
case string:
nt.Time, err = parseDateTime([]byte(v), time.UTC)
nt.Valid = (err == nil)
return
}
nt.Valid = false
return fmt.Errorf("can't convert %T to time.Time", value)
}
// Value implements the driver Valuer interface.
func (nt NullTime) Value() (driver.Value, error) {
if !nt.Valid {
return nil, nil
}
return nt.Time, nil
}
View on GitHub (pinned to c426bd9379)
Solutions
- Switch the scan target to the standard library sql.NullTime, which integrates with the driver's parseTime path.
- Set parseTime=true in the DSN so TIME/DATETIME columns are delivered as time.Time.
- If the source is a numeric epoch, scan into an int64/sql.NullInt64 and convert to time manually.
Example fix
// before
var nt mysql.NullTime
db.QueryRow("SELECT created_at FROM t WHERE id=?", id).Scan(&nt)
// after — standard library type, works with parseTime=true
var nt sql.NullTime
db.QueryRow("SELECT created_at FROM t WHERE id=?", id).Scan(&nt) Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the DSN decodes time columns to time.Time
db, err := sql.Open("mysql", "user:pass@/db?parseTime=true")
if err != nil { return err } Type guard
switch value.(type) {
case time.Time, []byte, string, nil:
var nt mysql.NullTime
_ = nt.Scan(value) // accepted by Scan
default:
return fmt.Errorf("NullTime.Scan does not accept %T", value)
} Try / catch
var nt mysql.NullTime
if err := rows.Scan(&nt); err != nil {
if strings.Contains(err.Error(), "can't convert") {
// source column is not a time/[]byte/string; scan into a matching type instead
}
} Prevention
- Prefer the standard sql.NullTime over mysql.NullTime.
- Set parseTime=true in the DSN for any TIME/DATETIME columns.
- Match the Scan destination type to the actual column type.
When it happens
Trigger: Scanning into a mysql.NullTime when the source column arrives as int64/float64 (e.g. a BIGINT timestamp column) rather than a time/[]byte/string; scanning a raw numeric or sql.Null* value into NullTime.
Common situations: Using mysql.NullTime instead of sql.NullTime; a column type changed from DATETIME to BIGINT; DSN lacks parseTime=true so a TIME column arrives as a non-time type that still is not one of the three accepted types.
Related errors
- invalid timeTruncate value: %v, error: %w
- bad value for field: `%c`
- illegal TIME length %d
- invalid TIME packet length %d
- cannot convert type: %T
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/966cc21fab4a54e9.json.
Report an issue: GitHub.