vitessio/vitess · error
Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Er
Error message
Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Error} What it means
WaitForReplicationStart polls SHOW SLAVE STATUS after issuing START SLAVE and aggregates any replication thread failures into a single error. When Last_SQL_Error (replica SQL thread) or Last_IO_Error (replica IO thread) is non-empty, they are joined with ", " and returned as one error. It reports why replication did not come up cleanly.
Source
Thrown at go/vt/mysqlctl/replication.go:157
if err != nil {
return err
}
if replicaStatus.Running() {
return nil
}
time.Sleep(time.Second)
}
errs := make([]string, 0, 2)
if replicaStatus.LastSQLError != "" {
errs = append(errs, "Last_SQL_Error: "+replicaStatus.LastSQLError)
}
if replicaStatus.LastIOError != "" {
errs = append(errs, "Last_IO_Error: "+replicaStatus.LastIOError)
}
if len(errs) != 0 {
return errors.New(strings.Join(errs, ", "))
}
return nil
}
// StartReplication starts replication.
func (mysqld *Mysqld) StartReplication(ctx context.Context, hookExtraEnv map[string]string) error {
conn, err := getPoolReconnect(ctx, mysqld.dbaPool)
if err != nil {
return err
}
defer conn.Recycle()
if err := mysqld.executeSuperQueryListConn(ctx, conn, []string{conn.Conn.StartReplicationCommand()}); err != nil {
return err
}
h := hook.NewSimpleHook("postflight_start_slave")
h.ExtraEnv = hookExtraEnvView on GitHub (pinned to 01a25a7d17)
Solutions
- Read the embedded Last_SQL_Error / Last_IO_Error text in the message — it names the underlying replication failure.
- For IO errors, verify replication credentials, master host/port, and network/TLS connectivity from the replica (CHECK REPLICA STATUS / SHOW REPLICA STATUS).
- For SQL errors, inspect the offending binlog event; skip with mysqlctl's error handling or re-provision the replica from a fresh backup.
- Re-run WaitForReplicationStart after fixing; ensure the replica threads actually restart (START REPLICA).
Example fix
// before
if err := WaitForReplicationStart(ctx, mysqld, 30*time.Second); err != nil {
log.Errorf("replication failed: %v", err)
}
// after
if err := WaitForReplicationStart(ctx, mysqld, 30*time.Second); err != nil {
if strings.Contains(err.Error(), "Last_IO_Error:") {
log.Warn("IO thread error, retrying after connectivity check", slog.Any("error", err))
// verify master reachability / credentials, then retry
} else {
return vterrors.Wrapf(err, "replication failed to start")
}
} Defensive patterns
Strategy: try-catch
Try / catch
err := mysqlctl.WaitForReplicationStart(ctx, mysqld, timeout)
if err != nil {
var ioErr, sqlErr bool
if strings.Contains(err.Error(), "Last_IO_Error:") {
ioErr = true
}
if strings.Contains(err.Error(), "Last_SQL_Error:") {
sqlErr = true
}
switch {
case ioErr:
// connectivity/credentials: bounded retry
case sqlErr:
// event-level failure: needs manual intervention
default:
return vterrors.Wrapf(err, "replication start")
}
} Prevention
- Validate replication credentials and master reachability before START REPLICA.
- Provision replicas from fresh backups so the SQL thread doesn't hit missing/duplicate data.
- Monitor SHOW REPLICA STATUS proactively to catch Last_IO_Error/Last_SQL_Error before automated waits fail.
- Use generous timeouts for WaitForReplicationStart; CI and slow networks need 30s+.
When it happens
Trigger: Calling WaitForReplicationStart (directly or via StartReplication paths, or during executeFullBackup) where replicaStatus.LastSQL_Error or replicaStatus.LastIO_Error is non-empty after the wait window; the strings are concatenated as "Last_SQL_Error: <val>, Last_IO_Error: <val>" and returned.
Common situations: Replica IO thread can't connect to the master (wrong credentials/host, network partition, TLS mismatch); SQL thread halted by a duplicate-key or corrupt relay-log error; starting replication against a misprovisioned replica after restore.
Related errors
- GetPreviousGTIDs: previous GTIDs not found
- ErrNoSemiSync
- no rpl_semi_sync_replica_status variable in mysql
- startPos.GTIDSet is wrong type - expected filePosGTID, got:
- failed to set @source_binlog_checksum=@@global.binlog_checks
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/63569120e10da2c6.
Report an issue: GitHub.