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.

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.

Appendix: 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)