micro/go-micro · error

Couldn't insert record ${key}

Error message

Couldn't insert record ${key}

What it means

sqlStore.Write wraps any error from the prepared INSERT ... ON DUPLICATE KEY UPDATE statement with the record key so the developer knows which write failed. It means MySQL rejected the upsert for this specific record, not that the store is misconfigured (that fails earlier in initDB).

Source

Thrown at store/mysql/mysql.go:122

		return records, err
	}
	if cachedTime.Before(time.Now()) {
		// record has expired
		go func() { _ = s.Delete(key) }()
		return records, store.ErrNotFound
	}
	record.Expiry = time.Until(cachedTime)
	records = append(records, record)

	return records, nil
}

// Write records.
func (s *sqlStore) Write(r *store.Record, opts ...store.WriteOption) error {
	timeCached := time.Now().Add(r.Expiry)
	_, err := s.writePrepare.Exec(r.Key, r.Value, timeCached, r.Value, timeCached)
	if err != nil {
		return errors.Wrap(err, "Couldn't insert record "+r.Key)
	}

	return nil
}

// Delete records with keys.
func (s *sqlStore) Delete(key string, opts ...store.DeleteOption) error {
	result, err := s.deletePrepare.Exec(key)
	if err != nil {
		return err
	}
	_, err = result.RowsAffected()
	if err != nil {
		return err
	}

	return nil
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Log the wrapped cause to identify the MySQL error code
  2. Check MySQL connectivity/max_allowed_packet if values are large
  3. Validate r.Expiry and r.Value sizes/content before calling Write
  4. Reconnect/retry the write; reconfigure the store if the connection pool died

Example fix

// before
s.Write(&store.Record{Key: k, Value: hugeBlob, Expiry: 0})
// after
if len(hugeBlob) < 16*1024*1024 {
    s.Write(&store.Record{Key: k, Value: hugeBlob, Expiry: time.Hour})
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate before Write
if r.Key == "" || len(r.Value) > maxAllowed {
    return errors.New("invalid record for mysql store")
}

Try / catch

if err := st.Write(rec); err != nil {
    if strings.Contains(err.Error(), "Couldn't insert record") {
        log.Printf("insert failed for key %s: %+v", rec.Key, err)
        // inspect MySQL error code and retry on lock timeouts
        return retryWrite(rec)
    }
    return err
}

Prevention

When it happens

Trigger: store.Write(&store.Record{Key: key, ...}) executes s.writePrepare.Exec(...) and MySQL returns an error: connection lost, value exceeds limits, invalid datetime for expiry, lock wait timeout, or table missing.

Common situations: MySQL server restarted or connection dropped mid-write; record value larger than max_allowed_packet; expiry timestamps out of range; deadlock/lock wait timeout under concurrent writes to the same key.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/decf4faefcde763b. Report an issue: GitHub.