vitessio/vitess · error
no read_only variable in mysql
Error message
no read_only variable in mysql
What it means
IsReadOnly runs "SHOW VARIABLES LIKE 'read_only'" via FetchSuperQuery and requires exactly one row. If no row comes back, mysqld is unreachable or the variable is missing, and this error is returned (with true as the conservative read-only answer). It signals the server state could not be determined, not that the server is genuinely read-only.
Source
Thrown at go/vt/mysqlctl/replication.go:822
finalRes := make(map[string]string, len(qr.Rows))
for _, row := range qr.Rows {
if len(row) != 2 {
return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "incorrect number of fields in the row")
}
finalRes[row[0].ToString()] = row[1].ToString()
}
return finalRes, nil
}
// IsReadOnly return true if the instance is read only
func (mysqld *Mysqld) IsReadOnly(ctx context.Context) (bool, error) {
qr, err := mysqld.FetchSuperQuery(ctx, "SHOW VARIABLES LIKE 'read_only'")
if err != nil {
return true, err
}
if len(qr.Rows) != 1 {
return true, errors.New("no read_only variable in mysql")
}
if qr.Rows[0][1].ToString() == "ON" {
return true, nil
}
return false, nil
}
// IsSuperReadOnly return true if the instance is super read only
func (mysqld *Mysqld) IsSuperReadOnly(ctx context.Context) (bool, error) {
qr, err := mysqld.FetchSuperQuery(ctx, "SELECT @@global.super_read_only")
if err != nil {
return false, err
}
if len(qr.Rows) == 1 {
sro := qr.Rows[0][0].ToString()
if sro == "1" || sro == "ON" {
return true, nilView on GitHub (pinned to 01a25a7d17)
Solutions
- Check mysqld process status and connectivity before calling IsReadOnly.
- Confirm the DBA/super-user credentials used by FetchSuperQuery are valid — auth failures often surface as missing rows.
- Treat the returned bool=true plus this error as 'unknown', and retry or fall back to process-level checks rather than assuming read-only state.
- If truly running a server without read_only, upgrade to a standard MySQL build.
Defensive patterns
Strategy: retry
Try / catch
readOnly, err := mysqld.IsReadOnly(ctx)
if err != nil {
if strings.Contains(err.Error(), "no read_only variable") {
// server unreachable: treat as unknown, bounded retry
return retryOrFallback(err)
}
return vterrors.Wrapf(err, "checking read_only")
} Prevention
- Gate IsReadOnly calls on prior health-check success (mysqld reachable).
- Use properly privileged DBA credentials so SHOW VARIABLES via super query always returns rows.
- Never treat (true, err) as 'definitely read-only' — the bool is conservative when the error is present.
When it happens
Trigger: Calling Mysqld.IsReadOnly when SHOW VARIABLES LIKE 'read_only' returns len(qr.Rows) != 1 — usually because mysqld is down or the DBA connection cannot be established, so the expected single row is missing.
Common situations: Tablet health checks during mysqld restart/maintenance windows; super-user connection failures (FetchSuperQuery needs sufficient privileges); nonstandard MySQL builds lacking the read_only variable.
Related errors
- no port variable in mysql
- can't get charset to check binlog stream: %v
- can't get charset to request binlog stream: %v
- failed query BEGIN, err: %s
- error in connecting to mysql db with connection %v, err %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/d2af9c63e0ad54e0.
Report an issue: GitHub.