vitessio/vitess · error
can't set charset for statement
Error message
can't set charset for statement %d in transaction %v: %v
What it means
Thrown by processTransaction when mysql.SetCharset fails while trying to switch the target connection's charset so a statement replays with the same charset it was logged with. Without this, statement text could be misinterpreted, so the transaction is aborted rather than replayed with wrong encoding.
Solutions
- Verify the charset/collation exists on the target: `SHOW COLLATION LIKE '<from logged stmtCharset>'`.
- Upgrade the target MySQL/Vitess version to support the source's charsets, or convert source tables to charsets the target supports.
- Ensure target server character-set config includes the needed charsets (`character_set_server`, available charsets).
- If the connection is the issue, restart the stream for a fresh dbConn.
Example fix
// before: target lacks utf8mb4_0900_ai_ci // mysql.SetCharset(dbConn, stmtCharset) // ER_UNKNOWN_COLLATION // after: upgrade target or align source // ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- on source
Defensive patterns
Strategy: validation
Validate before calling
// verify the source's charsets exist on the target before streaming
for _, cs := range sourceCharsets { // e.g. utf8mb4_0900_ai_ci
var n int
if err := targetDB.QueryRow(
"SELECT COUNT(*) FROM information_schema.COLLATIONS WHERE COLLATION_NAME = ?", cs,
).Scan(&n); err != nil || n == 0 {
return fmt.Errorf("target lacks collation %s: binlog replay would fail", cs)
}
} Prevention
- Align source and target MySQL major versions (utf8mb4_0900_* needs MySQL 8+)
- Convert source tables to charsets the target supports before replicating
- Check SHOW COLLATION on the target covers all source collations in use
When it happens
Trigger: mysql.SetCharset(dbClient.dbConn, stmtCharset) errors: the requested charset/collation doesn't exist on the target MySQL version, the connection is broken, or the source logged a charset the target server was not compiled/configured with.
Common situations: Replicating from MySQL 8 (utf8mb4 variants, newer collations like utf8mb4_0900_ai_ci) to an older target that lacks them; source and target MySQL versions diverged; connection dropped mid-transaction.
Related errors
- binlog stream client charset
- can't get charset to check binlog stream
- can't get charset to request binlog stream
- error in processing binlog event
- all vterrors states are not mapped to mysql errors
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/7030f1264d0212c7.
Report an issue: GitHub.
Appendix: source
Thrown at go/vt/binlog/binlogplayer/binlog_player.go:466
// Make sure the statement is replayed in the proper charset.
if dbClient, ok := blp.dbClient.(*dbClientImpl); ok {
var stmtCharset *binlogdatapb.Charset
if stmt.Charset != nil {
stmtCharset = stmt.Charset
} else {
// Streamer sends a nil Charset for statements that use the
// charset we specified in the request.
stmtCharset = blp.defaultCharset
}
if !proto.Equal(blp.currentCharset, stmtCharset) {
// In regular MySQL replication, the charset is silently adjusted as
// needed during event playback. Here we also adjust so that playback
// proceeds, but in Vitess-land this usually means a misconfigured
// server or a misbehaving client, so we spam the logs with warnings.
log.Warn(fmt.Sprintf("BinlogPlayer changing charset from %v to %v for statement %d in transaction %v", blp.currentCharset, stmtCharset, i, tx))
err = mysql.SetCharset(dbClient.dbConn, stmtCharset)
if err != nil {
return false, fmt.Errorf("can't set charset for statement %d in transaction %v: %v", i, tx, err)
}
blp.currentCharset = stmtCharset
}
}
if _, err = blp.exec(string(stmt.Sql)); err == nil {
continue
}
if sqlErr, ok := err.(*sqlerror.SQLError); ok && sqlErr.Number() == sqlerror.ERLockDeadlock {
// Deadlock: ask for retry
log.Info(fmt.Sprintf("Deadlock: %v", err))
if err = blp.dbClient.Rollback(); err != nil {
return false, err
}
return false, nil
}
_ = blp.dbClient.Rollback()
return false, err
}View on GitHub (pinned to 01a25a7d17)