{"record":{"id":"63569120e10da2c6","repo":"vitessio/vitess","slug":"last-sql-error-lastsql-error-last-io-error","errorCode":null,"errorMessage":"Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Error}","messagePattern":"Last_SQL_Error: (.+?), Last_IO_Error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/replication.go","lineNumber":157,"sourceCode":"\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif replicaStatus.Running() {\n\t\t\treturn nil\n\t\t}\n\t\ttime.Sleep(time.Second)\n\t}\n\terrs := make([]string, 0, 2)\n\tif replicaStatus.LastSQLError != \"\" {\n\t\terrs = append(errs, \"Last_SQL_Error: \"+replicaStatus.LastSQLError)\n\t}\n\tif replicaStatus.LastIOError != \"\" {\n\t\terrs = append(errs, \"Last_IO_Error: \"+replicaStatus.LastIOError)\n\t}\n\n\tif len(errs) != 0 {\n\t\treturn errors.New(strings.Join(errs, \", \"))\n\t}\n\treturn nil\n}\n\n// StartReplication starts replication.\nfunc (mysqld *Mysqld) StartReplication(ctx context.Context, hookExtraEnv map[string]string) error {\n\tconn, err := getPoolReconnect(ctx, mysqld.dbaPool)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer conn.Recycle()\n\n\tif err := mysqld.executeSuperQueryListConn(ctx, conn, []string{conn.Conn.StartReplicationCommand()}); err != nil {\n\t\treturn err\n\t}\n\n\th := hook.NewSimpleHook(\"postflight_start_slave\")\n\th.ExtraEnv = hookExtraEnv","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/replication.go#L139-L175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nif err := WaitForReplicationStart(ctx, mysqld, 30*time.Second); err != nil {\n    log.Errorf(\"replication failed: %v\", err)\n}\n\n// after\nif err := WaitForReplicationStart(ctx, mysqld, 30*time.Second); err != nil {\n    if strings.Contains(err.Error(), \"Last_IO_Error:\") {\n        log.Warn(\"IO thread error, retrying after connectivity check\", slog.Any(\"error\", err))\n        // verify master reachability / credentials, then retry\n    } else {\n        return vterrors.Wrapf(err, \"replication failed to start\")\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := mysqlctl.WaitForReplicationStart(ctx, mysqld, timeout)\nif err != nil {\n    var ioErr, sqlErr bool\n    if strings.Contains(err.Error(), \"Last_IO_Error:\") {\n        ioErr = true\n    }\n    if strings.Contains(err.Error(), \"Last_SQL_Error:\") {\n        sqlErr = true\n    }\n    switch {\n    case ioErr:\n        // connectivity/credentials: bounded retry\n    case sqlErr:\n        // event-level failure: needs manual intervention\n    default:\n        return vterrors.Wrapf(err, \"replication start\")\n    }\n}","preventionTips":["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+."],"tags":["mysql","replication","replica-status"],"backgroundTag":"replication-lag-or-thread-error","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}