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
- Log the wrapped cause to identify the MySQL error code
- Check MySQL connectivity/max_allowed_packet if values are large
- Validate r.Expiry and r.Value sizes/content before calling Write
- 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
- Keep record values under max_allowed_packet
- Validate expiry timestamps are within MySQL timestamp range
- Retry transient MySQL errors (1205 lock wait, 1213 deadlock)
- Monitor MySQL connection health to catch dropped sessions
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
- failed to prepare read statement
- failed to prepare write statement
- failed to prepare delete statement
- unsupported statement
- Error writing to the store
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/decf4faefcde763b.
Report an issue: GitHub.