go-sql-driver/mysql · error

bad value for field: `%c`

Error message

bad value for field: `%c`

What it means

Returned by parseDateTime (utils.go:121) when parsing a textual datetime and the byte at position 4 is not `-`. Position 4 is the year-month separator in the `YYYY-MM-DD ...` layout, so a wrong character means the string does not follow the expected format. parseDateTime is used when reading DATETIME/TIMESTAMP columns (with parseTime=true) and by nulltime.go.

Source

Thrown at utils.go:121

/******************************************************************************
*                           Time related utils                                *
******************************************************************************/

func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
	const base = "0000-00-00 00:00:00.000000"
	switch len(b) {
	case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM"
		if string(b) == base[:len(b)] {
			return time.Time{}, nil
		}

		year, err := parseByteYear(b)
		if err != nil {
			return time.Time{}, err
		}
		if b[4] != '-' {
			return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[4])
		}

		m, err := parseByte2Digits(b[5], b[6])
		if err != nil {
			return time.Time{}, err
		}
		month := time.Month(m)

		if b[7] != '-' {
			return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[7])
		}

		day, err := parseByte2Digits(b[8], b[9])
		if err != nil {
			return time.Time{}, err
		}
		if len(b) == 10 {
			return time.Date(year, month, day, 0, 0, 0, 0, loc), nil

View on GitHub (pinned to c426bd9379)

Solutions

  1. Inspect and fix the stored data so it matches `YYYY-MM-DD[ HH:MM:SS[.ffffff]]`.
  2. Ensure the application writes proper DATETIME values, not free-form strings.
  3. Tighten sql_mode on the server (STRICT_TRANS_TABLES) so malformed values cannot be stored.

Example fix

// before: column holds '2024/01/01 00:00:00'
SELECT dt FROM t; // parseDateTime fails on '/' at b[4]
// after: normalize the data
UPDATE t SET dt = REPLACE(dt, '/', '-') WHERE dt LIKE '____/__/__%';
Defensive patterns

Strategy: validation

Validate before calling

if len(s) >= 5 && s[4] != '-' {
    return fmt.Errorf("datetime %q has bad year-month separator", s)
}

Type guard

func looksLikeDatetime(s string) bool { return len(s) >= 10 && s[4] == '-' && s[7] == '-' }

Prevention

When it happens

Trigger: Reading a row where a DATETIME/TIMESTAMP-valued column contains a string whose 5th byte is not '-', e.g. a value stored as `2024/01/01 ...` (slash separator) or otherwise corrupted, while the column length is one of the accepted sizes (10,19,21-26). utils.go:120-121 fires.

Common situations: A non-standard datetime format inserted via loose sql_mode; a column that is declared DATETIME but holds malformed/legacy data; a character-set/encoding issue altering bytes; application code writing strings instead of proper datetime values.

Related errors


AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04). Data as JSON: /data/errors/90c6e55ad06c9cf2.json. Report an issue: GitHub.