vitessio/vitess · critical
cannot decode RelayLogFilePosition
Error message
cannot decode RelayLogFilePosition
What it means
Same panic family as error 1630 but for the RelayLogFilePosition field: ProtoToReplicationStatus calls DecodePosition on s.RelayLogFilePosition and panics if it cannot parse the 'file:pos' string. The panic name explicitly identifies the field so the bad value can be located. It guards against invalid relay-log position data entering ReplicationStatus.
Source
Thrown at go/mysql/replication/replication_status.go:153
pos, err := DecodePosition(s.Position)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode Position"))
}
relayPos, err := DecodePosition(s.RelayLogPosition)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode RelayLogPosition"))
}
filePos, err := DecodePosition(s.FilePosition)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode FilePosition"))
}
fileRelayPos, err := DecodePosition(s.RelayLogSourceBinlogEquivalentPosition)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode RelayLogSourceBinlogEquivalentPosition"))
}
relayFilePos, err := DecodePosition(s.RelayLogFilePosition)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode RelayLogFilePosition"))
}
var sid SID
if s.SourceUuid != "" {
sid, err = ParseSID(s.SourceUuid)
if err != nil {
panic(vterrors.Wrapf(err, "cannot decode SourceUUID"))
}
}
replstatus := ReplicationStatus{
Position: pos,
RelayLogPosition: relayPos,
FilePosition: filePos,
RelayLogSourceBinlogEquivalentPosition: fileRelayPos,
RelayLogFilePosition: relayFilePos,
SourceServerID: s.SourceServerId,
ReplicationLagSeconds: s.ReplicationLagSeconds,
ReplicationLagUnknown: s.ReplicationLagUnknown,
SQLDelay: s.SqlDelay,View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect s.RelayLogFilePosition and correct it to 'file:position' format.
- Pre-validate with mysql.DecodePosition before conversion.
- Regenerate the status from the tablet via a fresh status RPC instead of reusing stale/mutated protos.
Example fix
// before
status := mysql.ProtoToReplicationStatus(pb) // panics on bad RelayLogFilePosition
// after
if _, err := mysql.DecodePosition(pb.RelayLogFilePosition); err != nil {
return fmt.Errorf("bad RelayLogFilePosition %q: %w", pb.RelayLogFilePosition, err)
}
status := mysql.ProtoToReplicationStatus(pb) Defensive patterns
Strategy: validation
Validate before calling
if _, err := mysql.DecodePosition(pb.RelayLogFilePosition); err != nil {
return fmt.Errorf("invalid RelayLogFilePosition %q", pb.RelayLogFilePosition)
} Try / catch
defer func() { if r := recover(); r != nil { err = fmt.Errorf("conversion failed: %v", r) } }() Prevention
- Only build status protos through ReplicationStatusToProto.
- Validate position strings match 'file:offset' before passing them on.
- Regenerate stale protos from the source tablet instead of reusing serialized data.
When it happens
Trigger: ProtoToReplicationStatus (or callers findErrantGTIDs, FindPositionsOfAllCandidates, ReplicaWasRunning, replicaIOThreadWasRunning) receives a proto where RelayLogFilePosition is malformed — e.g. missing ':offset' suffix, non-numeric offset, or partially written data.
Common situations: Hand-built protos in tests/tooling, data corruption from external serialization round-trips, or copy-paste errors putting a GTID or UUID into the position field.
Related errors
- cannot decode RelayLogSourceBinlogEquivalentPosition
- cannot decode SourceUUID
- The receiver ReplicationStatus contained a Mysql56GTIDSet in
- Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Er
- GetPreviousGTIDs: previous GTIDs not found
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/3b62f28419e57352.
Report an issue: GitHub.