vitessio/vitess · error

can't get charset to request binlog stream: %v

Error message

can't get charset to request binlog stream: %v

What it means

Thrown by applyEvents when reading the charset of the local (target) MySQL connection via mysql.GetCharset fails, so the player cannot tell the stream server which charset to check statements against. It aborts the binlog stream request before any events are applied.

Source

Thrown at go/vt/binlog/binlogplayer/binlog_player.go:356

	if !ok {
		return fmt.Errorf("no binlog player client factory named %v", binlogPlayerProtocol)
	}
	blplClient := clientFactory()
	err = blplClient.Dial(ctx, blp.tablet)
	if err != nil {
		err := fmt.Errorf("error dialing binlog server: %v", err)
		log.Error(fmt.Sprint(err))
		return err
	}
	defer blplClient.Close()

	// Get the current charset of our connection, so we can ask the stream server
	// to check that they match. The streamer will also only send per-statement
	// charset data if that statement's charset is different from what we specify.
	if dbClient, ok := blp.dbClient.(*dbClientImpl); ok {
		blp.defaultCharset, err = mysql.GetCharset(dbClient.dbConn)
		if err != nil {
			return fmt.Errorf("can't get charset to request binlog stream: %v", err)
		}
		log.Info(fmt.Sprintf("original charset: %v", blp.defaultCharset))
		blp.currentCharset = blp.defaultCharset
		// Restore original charset when we're done.
		defer func() {
			// If the connection has been closed, there's no need to restore
			// this connection-specific setting.
			if dbClient.dbConn == nil {
				return
			}
			log.Info(fmt.Sprintf("restoring original charset %v", blp.defaultCharset))
			if csErr := mysql.SetCharset(dbClient.dbConn, blp.defaultCharset); csErr != nil {
				log.Error(fmt.Sprintf("can't restore original charset %v: %v", blp.defaultCharset, csErr))
			}
		}()
	}

	var stream BinlogTransactionStream

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the target tablet's MySQL connectivity and logs — re-establish the stream if the dbConn was closed.
  2. Verify the target MySQL version/flavor supports the charset system variables GetCharset queries.
  3. Restart the vreplication stream so a fresh dbClient connection is created.
  4. If targeting Vitess or a proxy, ensure charset variables are served; consider upgrading the target to a version that supports them.

Example fix

// before: continue with stale/broken connection
//   return fmt.Errorf("can't get charset to request binlog stream: %v", err)
// after: ensure connection health before streaming
//   if err := blp.dbClient.Reconnect(); err != nil { return err }
//   blp.defaultCharset, err = mysql.GetCharset(dbClient.dbConn)
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm target serves charset variables before streaming
rows, err := db.Query("SHOW VARIABLES LIKE 'character_set_connection'")
if err != nil {
    return fmt.Errorf("target does not expose charset variables: %w", err)
}
rows.Close()

Try / catch

// wrap the whole ApplyBinlogEvents call and surface charset failure distinctly
err := binlogplayer.ApplyBinlogEvents(ctx, blp)
if err != nil && strings.Contains(err.Error(), "can't get charset") {
    log.Error("target charset unavailable; check MySQL version/flavor of target")
    return err // restart stream for a fresh connection
}

Prevention

When it happens

Trigger: mysql.GetCharset(dbClient.dbConn) returns an error: the target DB connection is broken/closed, the underlying `SHOW VARIABLES LIKE 'character_set%'`-style query fails, or the server does not expose charset variables (unexpected MySQL flavor/version).

Common situations: Target vttablet's MySQL connection dropped mid-run; running against a MySQL flavor or proxy (e.g. older MariaDB, Vitess-as-target) that doesn't return the expected charset variables; connection pool recycled between Begin and this call.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/eb21f2ea9584ae70. Report an issue: GitHub.