vitessio/vitess · error

cannot decode FilePosition

Error message

cannot decode FilePosition

What it means

ProtoToReplicationStatus decodes the FilePosition field (the binlog file:position as a Position) and panics with a wrapped error if it cannot be decoded. As with the other fields, this fires only when the incoming Status proto contains an invalid FilePosition string.

Source

Thrown at go/mysql/replication/replication_status.go:145

		SemiSyncPrimaryStatus:                  s.SemiSyncPrimaryStatus,
		SemiSyncReplicaStatus:                  s.SemiSyncReplicaStatus,
	}
	return replstatuspb
}

// ProtoToReplicationStatus translates a proto Status, or panics.
func ProtoToReplicationStatus(s *replicationdatapb.Status) ReplicationStatus {
	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,

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Validate s.FilePosition decodes via DecodePosition before conversion
  2. Ensure the producer writes FilePosition using EncodePosition/valid GTID-set syntax
  3. Prefer the non-panicking decode path if you must tolerate legacy statuses

Example fix

// before
status := replication.ProtoToReplicationStatus(s)
// after
if _, err := replication.DecodePosition(s.FilePosition); err != nil {
	return vterrors.Wrapf(err, "invalid FilePosition %q", s.FilePosition)
}
status := replication.ProtoToReplicationStatus(s)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := replication.DecodePosition(s.FilePosition); err != nil {
	return vterrors.Wrapf(err, "invalid FilePosition %q", s.FilePosition)
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		log.Warn("FilePosition decode panic", slog.Any("panic", r), slog.String("raw", s.FilePosition))
	}
}()

Prevention

When it happens

Trigger: Calling ProtoToReplicationStatus with a Status whose FilePosition field is malformed — e.g. a legacy/foreign encoding of file-based positions or an empty string from an uninitialized proto.

Common situations: Integrations mixing file-based and GTID-based replication status; statuses synthesized by custom tooling writing FilePosition in a non-Position format; version-skewed clusters.

Related errors


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