vitessio/vitess · error

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

Error message

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

What it means

Streamer.Stream wraps a failure from mysql.GetCharset when it tries to read the MySQL server's default charset at the start of a binlog dump. Vitess requires the binlog-streaming client charset to match the server default, and if the server's charset cannot even be queried (via the dba connection), the stream is aborted. The inner error is the underlying protocol/query failure.

Source

Thrown at go/vt/binlog/binlog_streamer.go:204

		log.Info(fmt.Sprintf("stream ended @ %v, err = %v", stopPos, err))
	}()

	if bls.conn, err = NewBinlogConnection(bls.cp); err != nil {
		return err
	}
	defer bls.conn.Close()

	// Check that the default charsets match, if the client specified one.
	// Note that Streamer uses the settings for the 'dba' user, while
	// BinlogPlayer uses the 'filtered' user, so those are the ones whose charset
	// must match. Filtered replication should still succeed even with a default
	// mismatch, since we pass per-statement charset info. However, Vitess in
	// general doesn't support servers with different default charsets, so we
	// treat it as a configuration error.
	if bls.clientCharset != nil {
		cs, err := mysql.GetCharset(bls.conn.Conn)
		if err != nil {
			return fmt.Errorf("can't get charset to check binlog stream: %v", err)
		}
		log.Info(fmt.Sprintf("binlog stream client charset = %v, server charset = %v", bls.clientCharset, cs))
		if !proto.Equal(cs, bls.clientCharset) {
			return fmt.Errorf("binlog stream client charset (%v) doesn't match server (%v)", bls.clientCharset, cs)
		}
	}

	var events <-chan mysql.BinlogEvent
	var errs <-chan error
	if bls.timestamp != 0 {
		// MySQL 5.6 only: We are going to start reading the
		// logs from the beginning of a binlog file. That is
		// going to send us the PREVIOUS_GTIDS_EVENT that
		// contains the starting GTIDSet, and we will save
		// that as the current position.
		bls.usePreviousGTIDs = true
		events, errs, err = bls.conn.StartBinlogDumpFromBinlogBeforeTimestamp(ctx, bls.timestamp)
	} else if !bls.startPos.IsZero() {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check connectivity of the dba user/connection to the MySQL server and retry the stream
  2. Look at the wrapped inner error (%v) to identify the actual protocol/query failure and fix that root cause
  3. Verify the MySQL server version is one supported by Vitess's mysql client (supports the charset query)
  4. If the server is healthy, enable retry of the binlog stream at a higher level (vttablet's service restarts)
Defensive patterns

Strategy: retry

Validate before calling

// before streaming, verify the dba connection can report charset
cs, err := mysql.GetCharset(conn.Conn)
if err != nil {
	// retry connect / check server health before calling Stream
}

Try / catch

err := streamer.Stream(ctx)
if err != nil && strings.Contains(err.Error(), "can't get charset to check binlog stream") {
	// transient connection issue: reconnect and retry Stream
}

Prevention

When it happens

Trigger: Calling Stream (via StreamKeyRange or StreamTables) with a non-nil clientCharset where the dba connection to MySQL cannot answer the charset query — e.g. connection dropped just after connect, server refuses the metadata query, or an unsupported/failing server returns a protocol error.

Common situations: MySQL server restarted or failing mid-handshake; proxy/firewall killing the dba connection; older or non-MySQL servers that don't implement the charset metadata query Vitess uses; transient network errors at stream startup.

Related errors


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