vitessio/vitess · critical
failed to parse stop_pos column: %v
Error message
failed to parse stop_pos column: %v
What it means
The stop_pos column stores the position at which the vreplication stream should stop (empty means run indefinitely). replication.DecodePosition failed on its value, meaning the stored stop position is not a decodable GTID set.
Source
Thrown at go/vt/binlog/binlogplayer/binlog_player.go:599
return VRSettings{}, fmt.Errorf("checkpoint information not available in db for %v", uid)
}
vrRow := qr.Named().Row()
maxTPS, err := vrRow.ToInt64("max_tps")
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse max_tps column: %v", err)
}
maxReplicationLag, err := vrRow.ToInt64("max_replication_lag")
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse max_replication_lag column: %v", err)
}
startPos, err := DecodePosition(vrRow.AsString("pos", ""))
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse pos column: %v", err)
}
stopPos, err := replication.DecodePosition(vrRow.AsString("stop_pos", ""))
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse stop_pos column: %v", err)
}
workflowType, err := vrRow.ToInt32("workflow_type")
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse workflow_type column: %v", err)
}
workflowSubType, err := vrRow.ToInt32("workflow_sub_type")
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse workflow_sub_type column: %v", err)
}
deferSecondaryKeys, err := vrRow.ToBool("defer_secondary_keys")
if err != nil {
return VRSettings{}, fmt.Errorf("failed to parse defer_secondary_keys column: %v", err)
}
options := vrRow.AsString("options", "{}")
var workflowOptions vtctldata.WorkflowOptions
if err := json.Unmarshal([]byte(options), &workflowOptions); err != nil {
return VRSettings{}, fmt.Errorf("failed to parse options column: %v", err)
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect: `select uid, stop_pos from _vt.vreplication where uid=<id>`.
- Fix or clear it: `update _vt.vreplication set stop_pos='' where uid=<id>` to run without a stop point, or set a valid encoded GTID set.
- If a stop point is required, capture it properly from the source (`SELECT @@global.gtid_executed`) and encode with the same flavor.
- Prefer workflow-level commands (e.g. MoveTables complete) over hand-editing stop_pos.
Example fix
// before: malformed stop point update _vt.vreplication set stop_pos='1-5' where uid=1; // after: valid GTID set or empty to disable update _vt.vreplication set stop_pos='' where uid=1;
Defensive patterns
Strategy: validation
Validate before calling
qr, _ := dbClient.ExecuteFetch(fmt.Sprintf("SELECT stop_pos FROM _vt.vreplication WHERE uid=%d", uid), 1)
if len(qr.Rows) == 1 {
sp := qr.Named().Row().AsString("stop_pos", "")
if sp != "" {
if _, err := replication.DecodePosition(sp); err != nil {
return fmt.Errorf("stop_pos %q invalid; clear it or set a valid GTID set", sp)
}
}
} Type guard
func isValidStopPos(sp string) bool {
if sp == "" { return true } // empty means run indefinitely
_, err := replication.DecodePosition(sp)
return err == nil
} Try / catch
settings, err := binlogplayer.ReadVRSettings(dbClient, uid)
if err != nil && strings.Contains(err.Error(), "failed to parse stop_pos") {
_, _ = dbClient.ExecuteFetch(fmt.Sprintf("UPDATE _vt.vreplication SET stop_pos='' WHERE uid=%d", uid), 0)
settings, err = binlogplayer.ReadVRSettings(dbClient, uid)
} Prevention
- Set stop points via workflow tooling, not raw SQL.
- Empty stop_pos is valid and means 'never stop' — clear rather than guess.
- Capture positions with the same MySQL flavor that will decode them.
- Validate with replication.DecodePosition before writing.
When it happens
Trigger: DecodePosition on stop_pos fails: manually entered stop position in the wrong format, flavor mismatch (MariaDB vs MySQL GTID), truncated value, or a stray non-empty invalid string left after workflow edits.
Common situations: Users setting a stop point via direct SQL instead of the workflow API; cross-flavor restore; copy-paste of a position with a typo.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse pos column: %v
- failed to parse max_tps column: %v
- failed to parse max_replication_lag column: %v
- failed to parse options column: %v
- empty gtid passed to setPosition
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/5a532aa46cbc8f6a.
Report an issue: GitHub.